当前位置: 首页 > news >正文

五、cv::SparseMat的介绍和使用

文章目录

    • 一、cv::SparseMat的概述
    • 二、稀疏数组的创建
      • 2.1 基本语法
      • 2.2 创建稀疏数组的几种方式
      • 2.3 设置元素值(赋值)
      • 2.4 完整示例:创建 + 赋值 + 遍历
    • 三、稀疏数组的访问方法
      • 3.1 ref<T>(const int* idx)
      • 3.2 find<T>(const int* idx)
      • 3.3 ptr<T>(Node* node)
      • 3.4 cv::SparseMat::value\<T>()
    • 四、示例操作

一、cv::SparseMat的概述

  cv::SparseMat 是 OpenCV 中用于 表示稀疏矩阵(Sparse Matrix)的类。和 cv::Mat 用于存储 稠密矩阵(Dense Matrix)不同,cv::SparseMat 更适合用来表示那些 大多数元素为零或空值 的多维数组。

适用场景:

  • 多维数组(如高维空间向量)。
  • 大部分值为默认值(0)的矩阵。
  • 需要节省内存,且不频繁对所有元素进行访问。

基本特性:

  • 支持任意维度(不像 cv::Mat 只支持 2D)。
  • 仅存储非零值(以哈希表形式实现)。
  • 不支持连续内存访问(不像 cv::Mat 支持指针连续区域)。

二、稀疏数组的创建

2.1 基本语法

cv::SparseMat::SparseMat(int dims, const int* sizes, int type);
  • dims:维度数量(比如2D就是2,3D就是3)。
  • sizes:每一维的大小,是一个数组。
  • type:OpenCV 类型(如 CV_32F、CV_8U 等)。

2.2 创建稀疏数组的几种方式

示例1:创建一个 2D 的稀疏矩阵(5x5,类型 float)

int sizes[] = {5, 5};  // 表示 2D:5 行 5 列
cv::SparseMat sparseMat(2, sizes, CV_32F);

示例2:创建一个 3D 稀疏矩阵(10×10×10)

int sizes[] = {10, 10, 10};
cv::SparseMat sparse3D(3, sizes, CV_8U);

示例3:使用 cv::Mat 的类型宏

int sizes[] = {8, 8};
cv::SparseMat sparseMat(2, sizes, CV_64FC1);  // 64位浮点数

2.3 设置元素值(赋值)

int idx[] = {2, 3};  // 设置 [2][3] 处的值
sparseMat.ref<float>(idx) = 1.23f;

注意:

  • ref() 会在访问位置上自动创建元素。
  • 若该位置已存在,则直接修改其值。

2.4 完整示例:创建 + 赋值 + 遍历

#include <opencv2/opencv.hpp>
#include <iostream>int main() {int sizes[] = {5, 5};cv::SparseMat sm(2, sizes, CV_32F);// 设置几个稀疏元素int idx1[] = {0, 1};int idx2[] = {2, 3};sm.ref<float>(idx1) = 10.0f;sm.ref<float>(idx2) = 20.5f;// 遍历所有非零项for (cv::SparseMatConstIterator it = sm.begin(); it != sm.end(); ++it) {const cv::SparseMat::Node* node = it.node();const float* val = it.ptr<float>();std::cout << "Index: [" << node->idx[0] << "][" << node->idx[1] << "]"<< " = " << *val << std::endl;}return 0;
}

三、稀疏数组的访问方法

3.1 ref(const int* idx)

功能:返回对某个位置元素的引用,如果该元素不存在,则创建并返回默认值(0)。

示例:

int idx[] = {1, 2};
sparseMat.ref<float>(idx) = 3.14f;  // 如果不存在,会自动创建

3.2 find(const int* idx)

功能:返回该位置的值,如果不存在,返回 默认值(0),不会创建新元素。

示例:

int idx[] = {1, 2};
float value = sparseMat.find<float>(idx);

3.3 ptr(Node* node)

功能:给定一个已存在的 Node* 节点,返回其值的指针。

示例:

for (cv::SparseMatConstIterator it = sparseMat.begin(); it != sparseMat.end(); ++it) {const float* val = it.ptr<float>();  // 获取值
}

3.4 cv::SparseMat::value<T>()

功能:用于访问 稀疏矩阵中当前迭代器位置处的值 的函数。它常用于与 cv::SparseMatConstIterator 或 cv::SparseMatIterator 一起,在遍历稀疏矩阵的所有非零元素时进行读取。

用于遍历 cv::SparseMat 的元素:

for (cv::SparseMatConstIterator it = sm.begin(); it != sm.end(); ++it) {float v = it.value<float>();// 使用 v 进行逻辑处理
}

与此等价的访问方式是:

const float* ptr = it.ptr<float>();
float v = *ptr;

但 value() 更简洁,适合只读场景。

示例:使用 value() 遍历稀疏矩阵

#include <opencv2/opencv.hpp>
#include <iostream>int main() {int sizes[] = {3, 3};cv::SparseMat sm(2, sizes, CV_32F);int idx1[] = {0, 1};int idx2[] = {2, 2};sm.ref<float>(idx1) = 5.0f;sm.ref<float>(idx2) = 10.0f;std::cout << "稀疏矩阵中所有非零元素:" << std::endl;for (cv::SparseMatConstIterator it = sm.begin(); it != sm.end(); ++it) {const cv::SparseMat::Node* node = it.node();float value = it.value<float>();  // 👈 使用 value() 获取值std::cout << "Index: [" << node->idx[0] << "][" << node->idx[1]<< "] = " << value << std::endl;}return 0;
}

四、示例操作

示例:创建一个 500x500 的单通道稀疏图像,并设置部分像素

#include <opencv2/opencv.hpp>
#include <iostream>int main() {// 定义尺寸int sizes[] = {500, 500};// 创建单通道 8 位稀疏矩阵cv::SparseMat sparseImg(2, sizes, CV_8UC1);// 设置部分像素值为非零uchar value = 255;sparseImg.ref<uchar>(100, 100) = value;  // 设置点 (100, 100) 为白色sparseImg.ref<uchar>(200, 200) = value;sparseImg.ref<uchar>(300, 300) = value;// 将稀疏图像转换为普通图像用于显示cv::Mat denseImg(500, 500, CV_8UC1, cv::Scalar(0)); // 全部为0cv::SparseMatConstIterator it = sparseImg.begin();cv::SparseMatConstIterator it_end = sparseImg.end();for (; it != it_end; ++it) {const cv::SparseMat::Node* node = it.node();int x = node->idx[0];int y = node->idx[1];denseImg.at<uchar>(x, y) = it.value<uchar>();}// 显示图像cv::imshow("Sparse to Dense Image", denseImg);cv::waitKey(0);return 0;
}

输出结果:
在这里插入图片描述
说明:

  • cv::SparseMat(2, sizes, CV_8UC1):创建一个 2 维稀疏矩阵,类型为单通道 8 位。
  • ref<uchar>(x, y):返回对稀疏矩阵中位置 (x, y) 的引用,若不存在则创建。

为了显示,为什么必须将稀疏图像转成稠密图像?
因为 OpenCV 的图像显示函数(如 cv::imshow)只支持稠密矩阵(cv::Mat),不支持稀疏矩阵(cv::SparseMat)。

原因详解:
1、疏矩阵不是图像格式:cv::SparseMat 本质上是一个稀疏存储结构,它只记录非零位置的索引和值,其内存布局和普通图像的连续二维像素数据完全不同。它并不知道一个“图像”的概念,也无法提供完整的像素数组供 GUI 函数使用。

例如:

sparseMat.ref<uchar>(100, 100) = 255;

这只是记录了 (100, 100) 位置为 255,其余像素都“假设”为 0,实际上并不存在于内存中。

2、imshow 需要一个完整的、连续的像素块:cv::imshow(name, image) 需要图像尺寸、每个像素在内存中的位置、通道、位深度、步长(stride)。这些信息 cv::Mat 都提供了,但 cv::SparseMat 由于数据稀疏、结构不连续,根本无法满足这些要求。

http://www.dtcms.com/a/308599.html

相关文章:

  • 是采用示例模板,还是采用json的结构化数据,哪种方式会让llm的输出更加稳定?
  • 查询目前服务器所占的带宽的命令(上传和下载)
  • CNN卷积神经网络之LeNet和AlexNet经典网络模型(三)
  • c语言的编译链接
  • Winform PathGradientBrush类使用
  • C#程序本地运行正常,通过网络下载报错:FileLoadException:“未能加载文件或程序集“xxx.dll”或它的某一个依赖项。
  • 【pycharm的使用】
  • Qwen3-30B-A3B-Thinking-2507 推理模型深度评测
  • 250721脑电分析课题进展——手工特征总结
  • lsof命令
  • SSO面临的问题
  • 为什么有时神经元会输出类似(甚至一样)?
  • 行业分享丨从工具应用到体系进化:东风商用车仿真体系建设与实践
  • 【源力觉醒 创作者计划】文心一言与deepseek集成springboot开发哪个更方便
  • 【力扣】面试经典150题总结01-数组/字符串
  • Dev-C++ 6.3 安装与使用指南:适合新手的C/C++编程工具
  • Allegro实用技巧-Snap-命令行移动
  • Android端RTMP低延迟播放器在工业与智能场景下的架构与落地
  • MySQL 中 CHAR 和 VARCHAR 类型有什么区别?
  • 一次性接收大量上传图片,后端优化方式
  • 【Git】Git 实战:完整拉取项目所有分支和标签,切换远程仓库,解决保护分支推送冲突
  • Linux Flathub软件管理方法 使用指南
  • 搭建个人博客
  • 决策树实现回归任务
  • 利用可观测性进行高效故障治理:从预防到改进的完整实践
  • 从Excel到工时管理系统:企业如何选择更高效的工时记录工具?
  • 第二十九章:AI的“原子与批次”:高维数据表示与操作精炼【总结前面(1)】
  • Windows 安全中心是什么?如何关闭 Windows 11 的安全中心
  • 算法导论第三版代码python实现与部分习题答案-第六章:堆排序
  • DooTask非营利性组织:让高效协作触手可及