在学习opencv的过程中我体验到,打好基础很重要,而了解opencv的数据类型就是打基础的一步,不了解透彻opencv的数据类型,在后期写代码,哪怕是抄代码都会是云里雾里。
本篇博文是我看《学习oepncv3》这本书第三章"了解opencv的数据类型"后所写。
opencv的数据类型大体有三类:
除了上面的三类,opencv还用到了很多标准模板库类(STL),我对这个也懂,但想来他应该是包含vector模板类的总称。可以看看其他CSDN博主是咋介绍STL的。https://blog.csdn.net/qq_40194498/article/details/79148874
下面我们就总结一下oepncv大体上都有哪些特有的数据类型。虽然现在啥类型都没说,但先在这儿概述一下是有利于理清框架的,否则后面一定会懵逼了,《学习oepncv3》的作者应该也是这么想的。
固定向量类,故名思意,就是大小(维度)已知的小型向量,大小已知,就非常利于我们处理于此有管关的操作(比如清理与保存)。
但是,我们一般在程序里很少见到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::Vec<>一样,cv::Matx<>一般也都以别名cv::Matx{1,2,3,4,6}{1,2,3,4,6}{f,d}的形式应用。
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
Scalar类本质上是一个四维Point类,但我们后面会发现,它常常用来表示颜色,因此叫他颜色Scalar类,它的四维分别为R,G,B以及透明度或者H,S,V以及透明度。该类对象的元素是通过整数下标访问的。
与Point类相似,这两个类继承自自己的模板,他们的区别在于cv::Size有width和height两个属性而不是x,y。儿cv::Rect包含了这四个。
Point类比较简单,他的函数列表也比较短,在此也不过多介绍了。
size类在实际操作中与Point类是类似的,而且可以与Point类相互转换,这两者之间主要的差别在于Point类的数据成员是x,y;而Size类中对应的成员是weidth,heigth;
size类的三个别名分别cv::Size,cv::Size2i,cv::Size2f;前面两个是等价的,表示整数大小,最后面一个表示32位浮点型大小。
矩阵类包含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。
功能函数包含数学操作,测试,错误生成,内存与线程处理,优化及其他工具。这里罗列一下几个:
对于4. cv::getTickCount() 这个函数,我们可以用它来测算我们程序的运行时间,大体思路为:
#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;
}
}
}
关于这个小程序有不理解的地方可以去这三篇博文看看。我是从这三篇搬运的。///
https://blog.csdn.net/jacke121/article/details/55045618
https://blog.csdn.net/wearlee/article/details/79693582
https://blog.csdn.net/sgc_bf/article/details/85796206
好了,正文到此就结束了,有问题欢迎评论区交流~!