【C++的OpenCV】第十四课-OpenCV基础强化(二):访问单通道Mat中的值之at()、ptr()、iscontinuous()

🎉🎉🎉 欢 迎 各 位 来 到 小 白 p i a o 的 学 习 空 间 ! \color{red}{欢迎各位来到小白piao的学习空间!} piao🎉🎉🎉
💖💖💖 持 续 更 新 , 期 待 关 注 ! \color{blue}{持续更新,期待关注!} 💖💖💖


我 的 主 页 : \color{purple}{我的主页:} 我的主页

  1. Python基础、中级、高级;
  2. C++数据结构和算法;
  3. Python数据结构和算法;
  4. OpenCV相关内容等重点内容

我 的 资 源 : \color{purple}{我的资源:} 我的资源

  1. IT技术各档次模板
  2. 各类项目(企业、毕设)
  3. 数据库安装包(Mysql8.0)
  4. 技能资料(电子书、软考等)

目录


----------------------------------以下为正式内容----------------------------------------

前 言 \color{purple}{前言}

        书接上回,我们继续来讨论有关Mat的基本知识,这次我们继续深化了解Mat对象,以便后期更好的进行开发工作。这一章节主要是一些使用层面的知识,相比上章节,我相信读者更愿意看本章内容,因为可以快速得到自己想要的结果,但是还是那句话,最好掌握原理之后,再去使用更为科学


前文链接:【C++的OpenCV】第十三课-OpenCV基础强化(一):绝对有用!Mat相关的一系列知识(基础->进阶)


一 、 访 问 的 方 法 \color{blue}{一、访问的方法} 访

1.1 利 用 成 员 函 数 a t ( ) \color{green}{1.1 利用成员函数at()} 1.1at()

        先来通过帮助文档了解一下at函数的基本信息:点击这里了解详情,总共有12种形式,这里为大家略微截图,大家可以自行阅读,我摘抄其中重点,其余感兴趣的可以做进一步了解:
![在这里插入图片描述](https://img-blog.csdnimg.cn/8348bd8fc8794491a72ce953b909a378.png

1.1.1 at函数的功能:

在这里插入图片描述        这么多英文懵了吧?懵了就对了,下边我给大家讲几句!!!😃
        大概意思就是说,这个方法会返回一个你所指定的数组元素的引用,而关于下标索引范围的检查动作仅仅在测试模式下生效(生产模式下不生效的目的是为了提高程序的执行效率)。注意:这里得到是某个元素的引用哦!!!
        再直白一点,就是说它可以得到矩阵的某行某列的元素。

1.1.2 多种at()函数原型的介绍及案例

a) 类型一:_Tp& cv::Mat::at ( int i = 0)
template<typename _Tp >
_Tp& cv::Mat::at ( int  i = 0) 	

        原文:That is, if, for example, A is a 1 x N floating-point matrix and B is an M x 1 integer matrix, you can simply write A.at<float>(k+4) and B.at<int>(2i+1) instead of A.at<float>(0,k+4) and B.at<int>(2i+1,0), respectively.
大概意思:这个参数i,可以指代任意一个单行或者单列的二维矩阵,例如:一个1行N列的浮点矩阵A,和一个M行1列的整型矩阵B,分别找到其中某个元素的方法就可以简化为:A.at<float>(k+4) 和 B.at<int>(2*i+1)。
        注意:这里函数原型中的返回值部分是_TP&哦,大家知道这是什么意思吧?(&是引用)
        这里来给大家一个使用上的要求:

If matrix is of type CV_8U then use Mat.at<uchar>(y,x).如果矩阵是CV_8U的类型,那么使用模版时类型也要是对应的数据类型uchar,即:Mat.at<uchar>(y,x)这里和大家解释一个细节:8U的意思就是8bit的无符号整数。If matrix is of type CV_8S then use Mat.at<schar>(y,x).同上的翻译,一个意思,即类型是CV_8S,则使用类型为schar,即:Mat.at<schar>(y,x),下边不再赘述。If matrix is of type CV_16U then use Mat.at<ushort>(y,x).If matrix is of type CV_16S then use Mat.at<short>(y,x).If matrix is of type CV_32S then use Mat.at<int>(y,x).If matrix is of type CV_32F then use Mat.at<float>(y,x).If matrix is of type CV_64F then use Mat.at<double>(y,x).
b) 类型二:_Tp& cv::Mat::at( int row,int col )
template<typename _Tp >
_Tp& cv::Mat::at( int row,int col ) 		

        那这种就是最常见的那种咯,输入行列找到对应的值咯。给大家个例子:

#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>using namespace cv;int main()
{Mat m = (Mat_<int>(3,2) << 1,2,3,4,5,6)cout << m.at<int>(1,1)<< endl; // 这里的结果是:4 ,为什么知道吗?cout << m <<endl; // 注意:显示的是3行2列//首先,这里创建的是一个3行2列的矩阵,这个不难懂,4是出现在第二行第二列的元素:/*[1,23,45,6]*/// 那这个m.at<int>(1,1)中的两个1,其实就得知道at的参数含义了,//注意,at()方法中的row和col都是从0开始的,0即代表第一行或者第一列,明白了吧?//注意:at()中是先行后列!return 0;
}
c)类型三 :_Tp& cv::Mat::at ( Point pt)
template<typename _Tp >
_Tp& cv::Mat::at ( Point  	pt) 	

        其实这种也很常见以及其返回const类型的方法都是一个原理,这里需要传入一个点对象作为参数,说白了,就是按照点的位置在对应矩阵这种查找对应的元素即可了。举个例:

#include<iostream>
#include"opencv2/core/utility.hpp"
using namespace std;
using namespace cv;int main()
{Mat m = (Mat_<int>(3,2) << 1,2,3,4,5,6);cout<<m<<endl;/*[1, 2;3, 4;5, 6]*/cout << m.at<int>(Point(1,0)) << endl; // 结果是2哦,看看上一节内容就知道,Point(c,r),是先列后行,且这两个值都是列和行的索引(基于0)return 0;
}

在这里插入图片描述
        虽然方法很多,其他的方法都可以触类旁通,只要学好C++的基础语法,这都不是难事哦,后期我也将会为大家写写C++和Python的基础教程,大家都可以持续关注起来哦!

1.2 利 用 成 员 函 数 p t r ( ) \color{green}{1.2利用成员函数ptr()} 1.2ptr()

        先来通过帮助文档了解一下at函数的基本信息:点击这里了解详情,这个方法更多,有20种,是不是看文档很累?看我的吧,帮你总结好了学习的方法,轻松上手,熟练掌握!
在这里插入图片描述

1.2.1 ptr()函数的功能

        首先呢,它会返回一个指向矩阵中某元素(或者行)的指针!注意哦,返回的是指针!并且哦,这个指针是uchar类型的哦!

1.2.2 多种ptr()函数原型介绍及案例

a) 类型一:uchar* cv::Mat::ptr ( int i0 = 0 )
 // 这个是模版方法:template<typename _Tp >
_Tp* cv::Mat::ptr 	( 	int  	i0 = 0	) 	// i0 :基于0的行索引,说白了,从零开始!//个人而言,更乐意直接使用模版方法,因为它可以返回模版类型的指针(行或者元素),而不是单纯的uchar*!!//以下这个是基础款:
uchar* cv::Mat::ptr (int  i0 = 0) 	

        注意,这个方法!返回的就是某一行的行指针!
        举个浅显易懂的例子吧:

#include<iostream>
#include"opencv2/core/utility.hpp"
using namespace std;
using namespace cv;int main()
{Mat m = (Mat_<int>(3,2) << 1,2,3,4,5,6);cout << m <<endl; // 注意:显示的是3行2列/*[1, 2;3, 4;5, 6]*/cout << m.size() << endl; // [2 x 3] 注意:size()的表示方式是2列3行!for(int r=0; r < m.rows; r++){//得到每行的行首指针,r就是当前行的索引const int* rptr = m.ptr<int>(r);//打印第r行的元素的所有值:for(int c=0; c<m.cols; c++){ //c是列的索引,也是基于0的索引,几乎所有数字型索引都是从0开始!cout<<rptr[c]<<",";}cout<<endl; //换行}return 0;
}

        结果如下:
在这里插入图片描述

b) 类型二:uchar* cv::Mat::ptr ( int row,int col )
// 这个是模板:template<typename _Tp >
_Tp* cv::Mat::ptr 	( 	int  	row,int  	col ) 		//以下这个是基础款:
uchar* cv::Mat::ptr ( int  row,int  col ) 		

        这种方式不就更直接了吗?直接通过行列访问到对应元素上(注意此时这个返回值就是直接返回元素的指针了!),我们试试看:

#include<iostream>
#include"opencv2/core/utility.hpp"
using namespace std;
using namespace cv;int main()
{Mat m = (Mat_<int>(3,2) << 1,2,3,4,5,6);cout << m <<endl; // 注意:显示的是3行2列/*[1, 2;3, 4;5, 6]*/cout << m.size() << endl; // [2 x 3] 注意:size()的表示方式是2列3行!cout << *m.ptr<int>(1,1) << endl; //注意这里一个细节哦,仔细看哦,结果是4//这里m.ptr<int>(1,1)得到的是索引为(1,1)的元素的指针!//而在其之前加上*号就是获取该指针地址对应的元素(这个过程通常被称为“解引用”操作)return 0;
}

        看着方法众多,很多方法几乎用不到,但是得有这个功能,新手先掌握这些,剩下的内容等用到了再查就行!掌握了规律,剩下的无师自通了哈!

1.3 利 用 成 员 函 数 i s C o n t i n u o u s 和 p t r \color{green}{1.3利用成员函数isContinuous和ptr} 1.3isContinuousptr

1.3.1 isContinuous()介绍

        原文链接得有:点击这里了解详情,毕竟是教大家学东西,同时培养自学能力,这么良心的作者已经很少了!
        函数功能:
        **如果矩阵元素连续存储,且每行末尾没有间隙,则该方法返回true。否则,它将返回false。**显然,1x1或1xN矩阵总是连续的。使用Mat::create创建的矩阵总是连续的。但是,如果 使用Mat::col、Mat::diag等提取矩阵的一部分,或者为外部分配的数据构造矩阵头,则此类矩阵可能不再具有此属性。 想想看,图像边界连续性检测不就是这个原理吗?

        💖这里,为了给大家更好的理解,我们加一节小灶:Mat对象至少一行中的所有元素在内存汇总的排布是连续的!而行与行之间不一定连续(除非你用create创建Mat),如果不连续,其行与行的间隔也是一样的!!
在这里插入图片描述

        函数的原型:

bool cv::Mat::isContinuous ( ) const// 返回值是一个布尔值,如果是连续的就是true,否则就是false呗!

1.3.2 我们来看看其和ptr()组合如何完成实际需求(访问Mat中的值)

        这里就不废话了,都是讲过的内容,直接上代码:

#include<iostream>
#include"opencv2/core/utility.hpp"
using namespace std;
using namespace cv;int main()
{Mat m = (Mat_<int>(3,2) << 1,2,3,4,5,6);cout << m <<endl; // 注意:显示的是3行2列/*[1, 2;3, 4;5, 6]*/if(m.isContinuous()){int* ptr = m.ptr<int>(0); // 得到第一行行首指针for(int n = 0; n < m.rows*m.cols; n++){//解释一下:n < m.rows*m.cols这个边界条件是一种经验!//意思:m.rows*m.cols即行数*列数//其次,在内存层面上,如果矩阵连续(m.isContinuous()的结果为true),//就是说内存上这些值都是挨着存储的,所以索引也是连续的//故这是一个以为数组,则最大索引就是m.rows*m.cols-1//怎么样?有意思吧?认真学习起来。cout<<ptr[n]<<",";}}return 0;
}

        注 意 仔 细 看 , 上 述 代 码 如 下 的 结 果 \color{red}{注意仔细看,上述代码如下的结果}
在这里插入图片描述
        说明上述代码不连续哦,当然你也可以尝试一下加一个else结构去打印一下“不连续”!证明,这样子创建的矩阵,每行之间是有固定间隙的哦(仔细看下下边的内容)!

在这里插入图片描述        那我们来换一种方式:

#include<iostream>
#include"opencv2/core/utility.hpp"
using namespace std;
using namespace cv;int main()
{Mat m = (Mat_<int>(3,2) << 1,2,3,4,5,6);Mat m_c;m_c.create(m.size(),m.type());//注意上文提到过:create创建的是连续存储的矩阵cout << m_c <<endl; // 注意:显示的是3行2列/*[1, 2;3, 4;5, 6]*/if(m.isContinuous()){int* ptr = m_c.ptr<int>(0); // 得到第一行行首指针for(int n = 0; n < m_c.rows*m_c.cols; n++){cout<<ptr[n]<<",";}cout<<endl;}return 0;
}

        这下结果明朗了,顺道学习了新技能!
在这里插入图片描述

四 、 总 结 \color{red}{四、总结}

内容虽然不多,分成两章更新,下章还在持续更新!但都是精华如果你觉得内容难懂,不妨从最基础的内容学起来,请看我的首页哦!我的主页
       

顺道呢,发现一个不错的资源:点我进入

其中包含了opencv入门的保姆级教程(环境的安装—>实际的项目【人脸识别&教程】,以及配套了一本中文版OpenCV书籍)


💖💖💖 持 续 更 新 , 期 待 关 注 ! \color{blue}{持续更新,期待关注!} 💖💖💖

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/124488.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Netty复习:(2)IdleStateHandler的用法

一、handler定义&#xff1a; package handler;import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter;public class MyChatServerHandler3 extends ChannelInboundHandlerAdapter {Overridepublic void userEventTriggered(…

UTC时间戳与北京时间转换

文章目录 前言一、几个时间相关的概念二、场景三、验证方法四、源码五、运行结果六、资源自取 前言 在应用中用到了 UTC 时间戳与北京时间进行转换的需求&#xff0c;这里做一个记录&#xff0c;方便后面有需求时直接拿来用。 一、几个时间相关的概念 GMT 时间&#xff1a;Gr…

SpringBoot内置工具类之断言Assert的使用与部分解析

2023.10.29更新&#xff1a; 使用assert的不利之处&#xff1a; 1、assert关键字需要在运行时候显式开启才能生效&#xff0c;否则你的断言就没有任何意义。而现在主流的Java IDE工具默认都没有开启-ea断言检查功能。这就意味着你如果使用IDE工具编码&#xff0c;调试运行时候…

ASP.NET WebApi 极简依赖注入

文章目录 环境服务类启动项注入使用依赖注入的优点 环境 .NET Core 7.0ASP.NET CoreVisual Studio 2022 服务类 public class T_TempService {public T_TempService(){}public void Test(){}}启动项注入 #region 依赖注入 builder.Services.AddTransient<T_TempService&g…

滑动窗口限流算法实现一

固定算法 原理&#xff1a;固定算法是将时间线分隔成固定大小的时间窗口&#xff0c;每个窗口都会有个计数器&#xff0c;用来记录窗口时间范围内的请求总数&#xff0c;如果窗口的请求总数达到最大限定值&#xff0c;会认定流量超限。比如将窗口大小设为1分钟&#xff0c;每分…

科大讯飞勾勒生成式AI输入法“模样”,开启下一代输入法革命

回顾国内第三方输入法赛道近十余年的发展&#xff0c;移动互联网的市场红利催生了科大讯飞、百度、搜狗等颇具规模和实力的头部厂商。与此同时&#xff0c;历经多年、多方角逐&#xff0c;第三方输入法市场进入存量阶段&#xff0c;升级技术、优化用户体验来挖掘存量&#xff0…

Rest风格基本语法与实战

1&#xff0c;前置知识点 1.1 GetMapping&#xff0c;PostMapping&#xff0c;PutMapping&#xff0c;DeleteMapping 平时我们都是使用RequestMapping&#xff0c;然后通过它的method属性来指定请求的方式&#xff0c;这样是有些麻烦的&#xff0c;然后这四个标签就是来简化这…

MySQL安装『适用于 CentOS 7』

✨个人主页&#xff1a; 北 海 &#x1f389;所属专栏&#xff1a; MySQL 学习 &#x1f383;操作环境&#xff1a; CentOS 7.6 腾讯云远程服务器 &#x1f381;软件版本&#xff1a; MySQL 5.7.44 文章目录 1.MySQL 的清理与安装1.1查看是否存在 MySQL 服务1.2.卸载原有服务1.…

JS逆向基础之反调试

JS逆向基础之反调试 截至目前的话大家应该都知道我们在进行js逆向的时候需要打开浏览器开发者工具进行网页的调试&#xff0c;但是在有时候网站会阻止我们去调试它的代码&#xff0c;而其阻止我们的手段也是多种多样的。接下来我们就来简单了解一下逆向过程中常见的反调试手段…

keealived安装配置启动

1.keepalived作用和原理图 keepalived作用:解决单点故障简单原理图1: 2.keepalived安装配置启动 地址: https://www.keepalived.org/download.html# 1)解压 tar -zxvf keepalived-2.0.18.tar.gz # 2)进入keepalived目录 cd keepalived-2.0.18/ # 3)安装libnl/libnl-3依赖…

chat gpt 在开发当中的应用

chatgpt 出来已经有一段时间了&#xff0c;本人在开发的过程中也是有去使用。 经常使用的是讯飞大模型和通义千问&#xff0c;在使用的过程中&#xff0c;个人感觉讯飞大模型在写代码方面会比较智能。 比如问一个 sqlser 单表 数据量 几个亿如何处理的问题&#xff0c;讯飞会给…

C/C++ 飞翔的小鸟

载入问题&#xff1a; 解决之后效果&#xff1a; 放在main函数里面进行封装&#xff1a; 效果展示: 实现下坠 放进while&#xff08;1&#xff09;里面不断进入循环&#xff0c;每次进入循环&#xff0c;鸟的y坐标值就会发生变化&#xff0c;以此实现下下坠效果 效果展示&#…

Vue 数据绑定 和 数据渲染

目录 一、Vue快速入门 1.简介 : 2.MVVM : 3.准备工作 : 二、数据绑定 1.实例 : 2.验证 : 三、数据渲染 1.单向渲染 : 2.双向渲染 : 一、Vue快速入门 1.简介 : (1) Vue[/vju/]&#xff0c;是Vue.js的简称&#xff0c;是一个前端框架&#xff0c;常用于构建前端用户…

Flutter FittedBox

&#x1f525; 英文单词FittedBox &#x1f525; Fitted 通过有道翻译如下 &#xff1a; Box 通过有道翻译如下 &#xff1a; 对 FittedBox 的理解 我们可以将 FittedBox 理解为合适的盒子&#xff0c;将其它布局放到FittedBox这样一个盒子中&#xff0c;从而实现 盒子里面的…

kubernetes实验挑战二(troubleshoot pv pvc )

This 2-Node Kubernetes cluster is broken! Troubleshoot, fix the cluster issues and then deploy the objects according to the given architecture diagram to unlock our Image Gallery!! 1、 kubeconfig /root/.kube/config, User ‘kubernetes-admin’ Cluster: S…

SpringCloud(一) 服务架构的演变及注册RestTemplate实现服务的远程调用

目录 一, 服务架构的演变 1.1 单体架构 1.2 分布式架构 1.3 微服务 1.4 SpringCloud 二, 服务拆分和远程调用 2,1 服务拆分原则 2.2 服务拆分示例 2.3 创建相应数据库 2.4 实现远程调用示例 1, 更改需求 2, 注册RestTemplate实现远程调用 2.5 服务消费者和提供者 一…

【数据分析】上市公司半年报数据分析

前言 前文介绍过使用网络技术获取上市公司半年报数据的方法&#xff0c;本文将对获取到的数据进行简要的数据分析。 获取数据的代码介绍在下面的两篇文章中 【java爬虫】使用selenium获取某交易所公司半年报数据-CSDN博客 【java爬虫】公司半年报数据展示-CSDN博客 全量数…

Flutter笔记:完全基于Flutter绘图技术绘制一个精美的Dash图标(中)

Flutter笔记 完全基于Flutter绘图技术绘制一个精美的Dart语言吉祥物Dash&#xff08;中&#xff09; 作者&#xff1a;李俊才 &#xff08;jcLee95&#xff09;&#xff1a;https://blog.csdn.net/qq_28550263 邮箱 &#xff1a;291148484163.com 本文地址&#xff1a;https://…

微服务框架Consul--新手入门

Consul Consul 是由 HashiCorp 开发的一款软件工具&#xff0c;提供了一组功能&#xff0c;用于服务发现、配置管理和网络基础设施自动化。它旨在帮助组织管理现代分布式和微服务架构系统的复杂性。以下是Consul的一些关键方面和功能&#xff1a; 服务发现&#xff1a;Consul …

【Linux】centOS7安装配置及Linux的常用命令---超详细

一&#xff0c;centOS 1.1 centOS的概念 CentOS&#xff08;Community Enterprise Operating System&#xff09;是一个由社区支持的企业级操作系统&#xff0c;它是以Red Hat Enterprise Linux&#xff08;RHEL&#xff09;源代码为基础构建的。CentOS提供了一个稳定、可靠且…