学习Opencv(蝴蝶书/C++)——4.图形和大型数组类型(上)

2023-12-02 06:20

本文主要是介绍学习Opencv(蝴蝶书/C++)——4.图形和大型数组类型(上),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 1. cv::Mat类的成员变量
    • 1.1 flags
    • 1.2 cv::Mat::step
  • 2 存储方式,存储位置计算
    • 2.1 存储方式
    • 2.2 🌈存储位置计算
      • 2.2.1 基本计算公式
      • 2.2.1 step代码说明
      • 2.2.3 内存地址计算代码说明
  • 3 创建数据
    • 3.0 Mat的构成
      • 3.0.1 3.0版本之后的Mat
      • 3.0.2 cvMat
    • 3.1 构造函数
    • 3.2 🌈构造函数总结
  • 4 Mat访问(at<>, 迭代器和ptr)
    • 4.0 🌈数据类型(CV_16F)等
    • 4.1 🌈模板函数at<>()访问
      • 4.1.1 基本使用示例
      • 4.1.2 构造函数
    • 4.2 🌈数组迭代器访问
      • 4.2.1 示例(对比ptr效果,ptr一个小trick)
      • 4.2.2 构造函数MatConstIterator_和MatIterator_
      • 4.2.3 NAryMatIterator迭代器构造函数
    • 4.3 🌈ptr/指针访问(内存地址)
      • 4.3.1 示例
      • 4.3.2 构造函数
    • 4.4 三种访问方式速度比较
      • 4.4.1 基本说明
      • 4.4.2 代码

OpenCV库中的大部分函数,要么是cv::Mat类的成员,要么是使用cv::Mat类作为参数,要么就是把cv::Mat作为返回值,很少有函数和这三种都没有关系。

OpenCV中的cv::Mat就相当于Numpy中的array类型,是整个库最核心的概念,其它内容都是围绕这个概念建立起来的。

cv::Mat类表示N维稠密数组,cv::SparsesMat表示N维稀疏数组

1. cv::Mat类的成员变量

OpenCV2.x版本中的CvMat结构,与现在OpenCV3.x之后的还是有很大不同的。

现在的cv::Mat类的成员变量:

  • int flags,包括下面四种标志,
    • the magic signature,魔法标识
    • continuity flag,连续性标志
    • depth,深度
    • number of channels,通道数
  • int dims,表示矩阵的维度,>=2
  • int rows和int cols表示矩阵的高/行和宽/列,当维度>2时,这两个值无效,返回(-1,-1)
  • uchar * data,一个数据指针,指向数据真正存储的地方
  • MatStep step,定义矩阵的数据布局
  • MatSize size: Size(cols, rows) ,这是因为在Size的构造器里,rows和columns的参数顺序是相反的,如下:
    typedef Size2i cv::Size
    typedef Size_<int> cv::Size2i
    Size_ (_Tp _width, _Tp _height) size指定的先是宽cols,再是高rows
    

1.1 flags

以下回答来自chatGPT:

在 OpenCV 中,cv::Mat 类有一个特殊的成员变量 flags,它是一个整数,表示 cv::Mat 对象的属性和标志。

flags 的值是通过对不同的标志位进行按位或操作得到的,不同的标志位表示不同的属性和行为。以下是一些常用的 flags 标志和它们的作用:

  • cv::Mat::CONTINUOUS_FLAG:表示矩阵是连续的,即数据在内存中是按行存储的,没有间隔。
  • cv::Mat::DEPTH_MASK:表示矩阵的深度(数据类型),可以通过与 cv::Mat::DEPTH_MASK 进行按位与操作来提取深度值。
  • cv::Mat::CHANNELS_MASK:表示矩阵的通道数,可以通过与 cv::Mat::CHANNELS_MASK 进行按位与操作来提取通道数值。
  • cv::Mat::MAGIC_MASK:用于检测错误或非法的 cv::Mat 对象。
  • cv::Mat::TYPE_MASK:用于提取矩阵的类型信息,flags 中除去上述标志位以外的部分。

此外,还有一些特定的标志位,如 cv::Mat::CONTINUOUScv::Mat::CV_32S 等,用于表示特定的属性。

你可以使用 cv::Mat::flags 成员变量来获取 cv::Mat 对象的标志位,也可以使用 cv::Mat::type() 函数来获取矩阵的类型。例如:

cv::Mat image = cv::imread("image.jpg");
int flags = image.flags;
int type = image.type();

注意,通过 flags 获取的是一个整数,你可以通过按位与与按位右移等操作来提取具体的属性值。而通过 type() 函数获取的是一个表示类型的整数,通过与 CV_ 系列常量进行比较,可以获知矩阵的具体类型。

参考:

  • OpenCV学习之路(二)——Mat对象
  • 【OpenCV4】cv::Mat.isContinuous() 函数判断内存是否连续(c++
  • OpenCV】从Mat的flags中可以读到的信息,以及相关宏定义

1.2 cv::Mat::step

详见OpenCV:Mat中的step、elemSize和任意内存访问

在这里插入图片描述

2 存储方式,存储位置计算

2.1 存储方式

cv::Mat可以用来表示任意维度的数组,数组中数据的存储和n维光栅扫描顺序的类似。
如果是一维数组,其存储就是连续的;
如果是二维数组,数据被组织成行,然后按照行排列(以前数据结构里,数组排列的行优先)
如果是三维数组(plane),那就是每个plane先被逐行填满,然后plane再一个接一个。

例如:

有一维数组: [1,3,5,2,7]
其存储:①③⑤②⑦有二维数组(OpenCV里打印2d数组结果是这样的)[1,3,5,2,7;
1,3,5,2,7;
1,3,5,2,7]
其存储:①③⑤②⑦|①③⑤②⑦|①③⑤②⑦
一个|代表一行三维数组。。。无法直接使用std::cout打印,可以理解为
其存储:
①③⑤②⑦|①③⑤②⑦|①③⑤②⑦||①③⑤②⑦|①③⑤②⑦|①③⑤②⑦||①③⑤②⑦|①③⑤②⑦|①③⑤②⑦
一个|代表一行,一个||表示一个plane

2.2 🌈存储位置计算

2.2.1 基本计算公式

1.1 成员变量中可以知道,对于一个矩阵 M M M,其布局是由数组M.step[]所定义的,因此索引为 [ i 0 , i 1 . . . , i M . d i m s − 1 ] [i_0,i_1...,i_{M.dims-1}] [i0,i1...,iM.dims1]的元素(其中 0 ≤ i k ≤ M . s i z e [ k ] 0\leq i_k \leq M.size[k] 0ikM.size[k])的地址可以通过下式计算:
a d d r ( M i 0 , i 1 . . . , i M . d i m s − 1 ) = M . d a t a + M . s t e p [ 0 ] ∗ i 0 + M . s t e p [ 1 ] ∗ i 1 + . . . . + M . s t e p [ M . d i m s − 1 ] ∗ i M . d i m s − 1 addr(M_{i_0,i_1...,i_{M.dims-1}})=M.data+M.step[0]*i_0+M.step[1]*i_1+....+M.step[M.dims-1]*i_{M.dims-1} addr(M

这篇关于学习Opencv(蝴蝶书/C++)——4.图形和大型数组类型(上)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

C++如何通过Qt反射机制实现数据类序列化

《C++如何通过Qt反射机制实现数据类序列化》在C++工程中经常需要使用数据类,并对数据类进行存储、打印、调试等操作,所以本文就来聊聊C++如何通过Qt反射机制实现数据类序列化吧... 目录设计预期设计思路代码实现使用方法在 C++ 工程中经常需要使用数据类,并对数据类进行存储、打印、调试等操作。由于数据类

Linux下如何使用C++获取硬件信息

《Linux下如何使用C++获取硬件信息》这篇文章主要为大家详细介绍了如何使用C++实现获取CPU,主板,磁盘,BIOS信息等硬件信息,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下... 目录方法获取CPU信息:读取"/proc/cpuinfo"文件获取磁盘信息:读取"/proc/diskstats"文

Java数组初始化的五种方式

《Java数组初始化的五种方式》数组是Java中最基础且常用的数据结构之一,其初始化方式多样且各具特点,本文详细讲解Java数组初始化的五种方式,分析其适用场景、优劣势对比及注意事项,帮助避免常见陷阱... 目录1. 静态初始化:简洁但固定代码示例核心特点适用场景注意事项2. 动态初始化:灵活但需手动管理代

C++使用printf语句实现进制转换的示例代码

《C++使用printf语句实现进制转换的示例代码》在C语言中,printf函数可以直接实现部分进制转换功能,通过格式说明符(formatspecifier)快速输出不同进制的数值,下面给大家分享C+... 目录一、printf 原生支持的进制转换1. 十进制、八进制、十六进制转换2. 显示进制前缀3. 指

C++中初始化二维数组的几种常见方法

《C++中初始化二维数组的几种常见方法》本文详细介绍了在C++中初始化二维数组的不同方式,包括静态初始化、循环、全部为零、部分初始化、std::array和std::vector,以及std::vec... 目录1. 静态初始化2. 使用循环初始化3. 全部初始化为零4. 部分初始化5. 使用 std::a

shell编程之函数与数组的使用详解

《shell编程之函数与数组的使用详解》:本文主要介绍shell编程之函数与数组的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录shell函数函数的用法俩个数求和系统资源监控并报警函数函数变量的作用范围函数的参数递归函数shell数组获取数组的长度读取某下的

在PyCharm中安装PyTorch、torchvision和OpenCV详解

《在PyCharm中安装PyTorch、torchvision和OpenCV详解》:本文主要介绍在PyCharm中安装PyTorch、torchvision和OpenCV方式,具有很好的参考价值,... 目录PyCharm安装PyTorch、torchvision和OpenCV安装python安装PyTor

openCV中KNN算法的实现

《openCV中KNN算法的实现》KNN算法是一种简单且常用的分类算法,本文主要介绍了openCV中KNN算法的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录KNN算法流程使用OpenCV实现KNNOpenCV 是一个开源的跨平台计算机视觉库,它提供了各

OpenCV图像形态学的实现

《OpenCV图像形态学的实现》本文主要介绍了OpenCV图像形态学的实现,包括腐蚀、膨胀、开运算、闭运算、梯度运算、顶帽运算和黑帽运算,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起... 目录一、图像形态学简介二、腐蚀(Erosion)1. 原理2. OpenCV 实现三、膨胀China编程(

MySQL 中查询 VARCHAR 类型 JSON 数据的问题记录

《MySQL中查询VARCHAR类型JSON数据的问题记录》在数据库设计中,有时我们会将JSON数据存储在VARCHAR或TEXT类型字段中,本文将详细介绍如何在MySQL中有效查询存储为V... 目录一、问题背景二、mysql jsON 函数2.1 常用 JSON 函数三、查询示例3.1 基本查询3.2