博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Opencv学习笔记五:了解opencv的数据类型
阅读量:3949 次
发布时间:2019-05-24

本文共 3963 字,大约阅读时间需要 13 分钟。

前言

在学习opencv的过程中我体验到,打好基础很重要,而了解opencv的数据类型就是打基础的一步,不了解透彻opencv的数据类型,在后期写代码,哪怕是抄代码都会是云里雾里。

本篇博文是我看《学习oepncv3》这本书第三章"了解opencv的数据类型"后所写。
opencv的数据类型大体有三类:

  1. 直接从C++中继承的基础类型(如int和float等)。这些类型包括简单的数组和矩阵,同时也代表了一些简单的几何概念,比如点,矩阵,大小等。
  2. 第二类是辅助对象,这些对象代表更抽象的概念,比如垃圾收集指针类,用于数据切片的范围对象(ranges objiects)以及抽象的终止条件类等。不过我对于此类对象并不咋了解。也没遇见过。。这是第一次看见这些名词haha
  3. 第三类可以称为大型数据类型。典型代表就是cv::Mat类。这也是我们后面处理图像最常用到的数据类型

除了上面的三类,opencv还用到了很多标准模板库类(STL),我对这个也懂,但想来他应该是包含vector模板类的总称。可以看看其他CSDN博主是咋介绍STL的。

基础类型概述

下面我们就总结一下oepncv大体上都有哪些特有的数据类型。虽然现在啥类型都没说,但先在这儿概述一下是有利于理清框架的,否则后面一定会懵逼了,《学习oepncv3》的作者应该也是这么想的。

固定向量类cv::Vec<>

固定向量类,故名思意,就是大小(维度)已知的小型向量,大小已知,就非常利于我们处理于此有管关的操作(比如清理与保存)。

但是,我们一般在程序里很少见到cv::Vec<>这种这种写法,更常见的是他的别名,比如cv::Vec2i,cv::Vec3i,cv::Vec4d这种名称(分别对应 2个元素的整型向量,3个元素的整型向量,4的元素的双浮点向量),如果你仔细看一下,就会看出他的命名是很有规律的。
有着cv::Vec{2,3,4,6}{b,w,s,i,f,d}形式的声明,对于2到6个维度的6种数据类型的任何组合都是有效的。

固定矩阵类cv::Matx<>

cv::Matx<>设计用于一些特定的小型矩阵的操作,如cv::Vec<>一样,cv::Matx<>一般也都以别名cv::Matx{1,2,3,4,6}{1,2,3,4,6}{f,d}的形式应用。

点cv::Point类

cv::Point是两到三个原语类型的容器。可以表示二维或三位的点坐标。

cv::Point类是通过它们的成员是通过名称变量来访问的(mypoint.x,mypoint.y等),而不是通过下标访问(mypoint[0])。
如cv::Vec<>一样,Point类通过别名调用作为一个正确模板的实例。如cv::Point2i,cv::Point2f,cv::Point2d,cv::Point3i,cv::Point3f,cv::Point3d

颜色cv::Scalar类

Scalar类本质上是一个四维Point类,但我们后面会发现,它常常用来表示颜色,因此叫他颜色Scalar类,它的四维分别为R,G,B以及透明度或者H,S,V以及透明度。该类对象的元素是通过整数下标访问的。

cv::Size和cv::Rect类

与Point类相似,这两个类继承自自己的模板,他们的区别在于cv::Size有width和height两个属性而不是x,y。儿cv::Rect包含了这四个。

深入了解基础类型

Point类

Point类比较简单,他的函数列表也比较短,在此也不过多介绍了。

在这里插入图片描述

cv::Scalar类

在这里插入图片描述

Size类

size类在实际操作中与Point类是类似的,而且可以与Point类相互转换,这两者之间主要的差别在于Point类的数据成员是x,y;而Size类中对应的成员是weidth,heigth;

size类的三个别名分别cv::Size,cv::Size2i,cv::Size2f;前面两个是等价的,表示整数大小,最后面一个表示32位浮点型大小。
在这里插入图片描述

cv::Rect矩阵类

矩阵类包含Point类的成员函数X,Y(矩形左上角)和Size类的成员width和height(代表了矩阵的大小)。

在这里插入图片描述
cv::Rect也支持一系列的覆写操作符,它们可以用于计算两个矩形,一个矩形或别的对象的各种各样的几何特征。
在这里插入图片描述

固定矩阵类

固定矩阵类是为编译时就已知维度的矩阵打造的,这也是它成为固定的原因。因为它们内部的所有数据都是在堆栈上分配的,所以它们的分配和清除都很快。对固定矩阵类的操作运行很快,而且它们还在小型矩阵(22,33,等等)上做过特别的优化。

独立固定矩阵一般通过别名分配,cv::Matx{1,2,3,4,6}{1,2,3,4,6}{f,d}
因为固定向量矩阵支持的操作很多,这里先只列出几个常遇见的。
在这里插入图片描述

固定向量类

固定向量类是由固定矩阵类派生而来的。它们其实是为了跟方便的使用cv::Matx<>。有cv::Vec{2,3,4,6}{b,w,s,i,f,d}形式的声明

在这里插入图片描述

辅助对象

除了基本类型和大容器,还有一系列的辅助函数,它们对控制各式各样的算法(比如终止条件)和各种在容器上的操作(比如ranges后者slices)非常有用。这里我们只写一个cv::Range类。

cv::Range类用于确定一个连续的整数序列。cv::Range对象有两个元素start和end,它们经常在构造函数 cv::Range(int start, int end)中设定,范围包含初始值start,但不包含终止值end。

  • 使用size()函数可以得到一个range类的元素数量 range.size() ;
  • empty()函数用于检测一个range类是否含有元素。
  • range.all()可以在任何需要获得对象可用范围时使用

功能函数

功能函数包含数学操作,测试,错误生成,内存与线程处理,优化及其他工具。这里罗列一下几个:

  1. cv::getNumThreads() 获得当前Opencv使用的线程数
  2. cv::getThreadNum() 获得当前线程的索引
  3. cv::setNumThreads() 设定Opencv使用的线程数
  4. cv::getTickCount() 获得系统的tick数
  5. cvRound() 近似一个浮点数x到最近的整数

对于4. cv::getTickCount() 这个函数,我们可以用它来测算我们程序的运行时间,大体思路为:

  1. t = (double)cv::getTickCount(); 在程序开头进行读取当前系统的tick数,作为起始点
  2. t = ((double)cv::getTickCount() - t) / cv::getTickFrequency(); 在程序末尾计算经过的时间, // getTickcount函数:返回从操作系统启动到当前所经过的毫秒
    // getTickFrequency函数:返回每秒的计时周期数
    我们可以写一个计算摄像头的帧率的小程序:
#include "pch.h"#include 
#include
using namespace cv;using namespace std;int main(){
Mat frame; VideoCapture capture(0); //定义一个视频流对象 double fps; char string[10]; namedWindow("Camera FPS"); double t = 0; while (1) {
t = (double)getTickCount(); if (waitKey(1) == 1)break; if (capture.isOpened()) {
capture >> frame; t = t = ((double)cv::getTickCount() - t) / cv::getTickFrequency(); fps = 1.0 / t; sprintf_s(string, "%.2f", fps); // 帧率保留两位小数 //spintf函数容易望文生义,误以为是一个打印函数。实质上是一个字符串格式化命令。 //主要功能是把格式化的数据写入某个字符串中,至于需要打印的话,还是得需要打印函数来对其进行打印。 std::string fpsString("FPS:"); fpsString += string; // 在"FPS:"后加入帧率数值字符串 cout << fpsString << endl; cv::putText(frame, // 图像矩阵 fpsString, // string型文字内容 cv::Point(5, 20), // 文字坐标,以左下角为原点 cv::FONT_HERSHEY_SIMPLEX, // 字体类型 0.5, // 字体大小 cv::Scalar(0, 0, 0)); // 字体颜色 imshow("Camera FPS", frame); } else {
cout << "NO Camera Input! " << endl; break; } }}

在这里插入图片描述

关于这个小程序有不理解的地方可以去这三篇博文看看。我是从这三篇搬运的。///


好了,正文到此就结束了,有问题欢迎评论区交流~!

转载地址:http://qdewi.baihongyu.com/

你可能感兴趣的文章
linux下UEFI的管理
查看>>
类thinkpad笔记本安装deepinv20后启动黒屏的解决
查看>>
利用本地centos镜像升级centOS
查看>>
FreeBSD常用操作
查看>>
VC及esxi升级的必要性和步骤
查看>>
hp DL338服务器修改ilo管理地址
查看>>
vmware convert P2V 错误二三事
查看>>
让kali2020中的zsh有补完功能
查看>>
python解开压缩文件6位纯数字密码
查看>>
5620系列密码清除
查看>>
vncsever-centos&debian
查看>>
华为snmp模板
查看>>
kvm&xen挂载镜像文件
查看>>
SQL Server Union等操作时解决不同数据库字符集冲突的问题
查看>>
Linq GroupJoin(二)
查看>>
递归:访问页面的控件或文件夹的下文件
查看>>
DataGridView分頁控件
查看>>
Linq 使用entity framework查询视图返回重复记录的问题(转)
查看>>
项目中得到执行文件版本或其它信息
查看>>
WinForm DatagridView绑定大量数据卡顿的问题
查看>>