大纲

  1. 前置知识:C++中类(class)的相关知识
  2. 前置知识:C++中模板(template)的相关知识
  3. opencv中Vec类的定义及源码
  4. 引申:opencv中的宏定义如CV_8UC3

一、C++中的类
“类”是对对象的抽象,C++中的类实际上就是对一类具有相同特性的对象的交集,类相当于一种新的数据类型,数据类型不占用存储空间,用类型定义一个实体的时候,才会为它分配存储空间。
1.类的定义如下:

class 类名
{
成员类表
};

成员列表是类成员的集合,成员可以无限多,也可以没有;可以是数据,也可以是函数,成员函数如普通函数一样可以进行重载或者带默认参数。如果类成员中有函数的话,有以下两种定义方式:

在类内部定义函数体
class 类名
{
返回类型 函数名(形参列表)
{
函数体
} };
在类外部定义函数体
class 类名
{
返回类型 函数名(形参列表);
};
返回类型 类名 :: 函数名(形参列表)
{
函数体
}

前一种定义方式相当于内联函数,调用速度快,但是会占用额外的内存,后一种方式则为普通的外部函数,建议使用第二种方式定义。
如果使用后一种方式定义的话,需要注意C++中设置默认形参的动作之只能有一次,在类中声明时设置了默认参数,外部定义时就不能再重复设置。

class Test
{public:void Sum(int a=0,int b=0);
};
void Test::Sum(int a,int b)
//void Test::Sum(int a=0,int b=0)  错误
{cout<<a+b;
}

2.类成员的访问控制
类的每个成员都有着自己的访问属性,包括“public"、”private"、"protected
“public"通常包含成员函数、”private“通常包括一般的变量。对于外部用户像是全局函数、另一个类的成员函数,只能通过"public"来访问类的成员。如:

#include <iostream>using namespace std;class Test
{public:Test() {}Test(int x, int y) :a(x), b(y) {}void Sum();
private:int a, b;void minus()
};void Test::Sum()
{cout << a + b;
}
void Test::minus()
{cout << b - a;
}
int main()
{Test test2(3, 4);test2.Sum();  //可以运行cout << test2.a;   //无法访问test2.minus()   //无法访问return 0;
}

从而类的定义扩展为:

class 类名
{
public:
公有的数据成员和成员函数
protected:
保护的数据成员和成员函数
private:
私有的数据成员和成员函数
};

3.类成员的初始化
建立一个类的对象时,需要对对象进行初始化,因为在类里面是不能对成员进行进行初始化的(类是数据类型,不占用存储空间),初始化的过程通过构造函数来实现。构造函数是一个没有返回值、和类同名的成员函数,由于创建对象通常是在外部进行的,所以构造函数申明为”public",例下:

#include <iostream>using namespace std;class Test
{public:Test ();Test (int x,int y);void Sum();
private:int a,b;
};
Test::Test()
{}
Test::Test(int x,int y)
{a=x;b=y;
}
void Test::Sum()
{cout<<a+b;
}
int main()
{Test test(3,4);test.Sum();return 0;
}

第一个“Test()“为默认构造函数也叫无参构造函数,它没有形参,可以在后续过程中赋值而不需要立即初始化。使用方法即:

TEST test

如果类中没有默认构造函数的话会报错,但IDE通常情况下会自动生成默认构造函数(实际上是4种特定情况,参见:自动生成默认构造函数情况),但如果自己定义了一个有参的构造函数就如“TEST (int x int y)",那IDE就不会自动再生成。也就是说,如果类中无默认构造函数,也可以通过”TEST test“初始化,一旦类中只存在有参构造函数,就必须带参初始化。、

构造函数初始化列表
之前介绍的构造函数是利用函数体内赋值的方式完成初始化,但更常用的一种方法其实是构造函数初始化列表,如:

#include <iostream>using namespace std;class Test
{public:Test ();Test (int x,int y);void Sum();
private:int a,b;
};
Test::Test()
{}
Test::Test(int x,int y):a(x),b(y)  //构造初始化列表而非赋值
{}
void Test::Sum()
{cout<<a+b;
}
int main()
{Test test(3,4);test.Sum();return 0;
}

也可以更简洁的表述为:


class Test
{public:Test () {}Test (int x,int y):a(x),b(y) {}  //直接在类内部完成定义void Sum();
private:int a,b;
};

这种方式较函数内赋值一般情况下没有区别,但如果需要初始化的是类类型的成员,就需要使用构建函数初始化列表的方法了。如:

#include <iostream>using namespace std;class Test
{public:Test () {}Test (int x,int y):a(x),b(y) {}void Sum();
private:int a,b;
};void Test::Sum()
{cout<<a+b;
}
class AnotherTest
{public:AnotherTest(int i,int j):test(i,j) {test.Sum();}
private:Test test;
};
int main()
{AnotherTest test(3,4);return 0;
}

这里Anothertest类中含有一个数据类型为Test的成员,因此需要使用
初始化列表,注意因为在AnotherTest的构造函数里调用了Test类中的Sum成员函数,所以会有输出”7“,如果直接写test.test.Sum()是不会有输出值的,第二个test属于private类型,无法访问。

复制构造函数
复制构造函数顾名思义,通过一个已经存在的对象对另一个对象赋值初始化,常用形式为:

类名 (const 类名& obj)
{
函数体
}

例如:

#include <iostream>using namespace std;class Test
{public:Test () {}Test (int x ,int y):a(x),b(y) {}Test (const Test& t):a(t.a),b(t.b) {}void Sum();
private:int a,b;
};void Test::Sum()
{cout<<a+b;
}int main()
{Test test1(3,4);Test test2 = test1;test2.Sum();return 0;
}

如果不定义复制构造函数,以上对象也可以这样进行初始化,原因就是系统也会自己生成一个复制构造函数。

类的继承
类的继承允许在已有类的基础上建立新类,继承方式,c++提供了三中继承方式。
public(公有继承):基类中的公有和保护成员保持原属性,私有成员为基类私有。
private(私有继承):基类中的所有成员在派生类中都是私有的。
protected(保护继承):基类的公有成员和保护成员在派生类中成了保护成员,私有成员仍为基类私有。
继承的写法如下:

class 子类名:public/ptivate/prtected 父类名
{
成员
}

例矩形对平行四边形的继承:

#include <iostream>using namespace std;class Parallelogram
{public:Parallelogram(int a,int b):length(a),width(b) {}int getLength(){return length;}int getWidth() {return width;}
private:int length,width;
};
class Rectangle : public Parallelogram  //公有继承
{public:Rectangle(int a,int b):Parallelogram(a,b) {}  //先对基类中的数据成员进行初始化void Area()     //计算面积{cout<<getLength()*getWidth();}
};
int main()
{Rectangle r(3,4);r.Area();return 0;
}

至此,“类”相关知识介绍完毕。
二、C++中的模板
如果说类是对对象的抽象,那么模板就是对类的抽象,模板相当于具有相同特性的类的交集,它声明了一种类的模板,并且提供了一个或多个的虚拟类型参数,从而给出不同数据类型的同一特性类。

模板的定义
常用形式为:

template<class/typename 虚拟类型1, class/typename 虚拟类型2…>
class 类名
{
成员
}

以下给出了一个适用于float和int型比较的类模板。

template <class numtype> //声明一个模板,虚拟类型名为numtype
class Compare //类模板名为Compare
{public :Compare(numtype a,numtype b){x=a;y=b;}numtype max( ){return (x>y)?x:y;}numtype min( ){return (x<y)?x:y;}
private :numtype x,y;
};

需要注意这里的成员函数是在类里面定义的,如果是在类外定义的话不能使用一般类成员函数的定义方法

numtype Compare::max( ) {…}

而应该先声明类模板:

template <class numtype>
numtype Compare<numtype>::max( )
{return (x>y)?x:y;
}

模板的初始化
使用模板定义对象时的形式为:
类模板名<实际类型名> 对象名;
类模板名<实际类型名> 对象名(实参表列);
如:Compare<int> cmp; Compare<int> cmp(3,7);
至此,所需“模板”知识介绍完毕。

三、opencv中的 Vec类
opencv中经常使用Vec+数字+字母来定义变量,像是Vec4b,Vec3s,其实这就是一个向量模板类,首先它在任何时刻都是一个一维矩阵(即列向量),其次它的元素数据类型可变。这一模板类是对与Mat类的继承,其源码如下;

//【1】下面是OpenCv中定义---定义---向量模板类----的源代码
//【2】一个拥有非类型模板形参的---类模板-----向量模板类template<typename _Tp, int cn> class Vec : public Matx<_Tp, cn, 1>
{public:typedef _Tp value_type;enum { depth = DataDepth<_Tp>::value, channels = cn, type = CV_MAKETYPE(depth, channels) };//! default constructor//【1】向量类的默认构造函数Vec();//【1】向量类有参构造函数Vec(_Tp v0); //!< 1-element vector constructorVec(_Tp v0, _Tp v1); //!< 2-element vector constructorVec(_Tp v0, _Tp v1, _Tp v2); //!< 3-element vector constructorVec(_Tp v0, _Tp v1, _Tp v2, _Tp v3); //!< 4-element vector constructorVec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4); //!< 5-element vector constructorVec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5); //!< 6-element vector constructorVec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6); //!< 7-element vector constructorVec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7); //!< 8-element vector constructorVec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8); //!< 9-element vector constructorVec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8, _Tp v9); //!< 10-element vector constructorexplicit Vec(const _Tp* values);  //保证函数显式调用Vec(const Vec<_Tp, cn>& v);static Vec all(_Tp alpha);//! per-element multiplicationVec mul(const Vec<_Tp, cn>& v) const;//! conjugation (makes sense for complex numbers and quaternions)Vec conj() const;/*!cross product of the two 3D vectors.For other dimensionalities the exception is raised*/Vec cross(const Vec& v) const;//! convertion to another data typetemplate<typename T2> operator Vec<T2, cn>() const;//! conversion to 4-element CvScalar.operator CvScalar() const;/*! element access */const _Tp& operator [](int i) const;_Tp& operator[](int i);const _Tp& operator ()(int i) const;_Tp& operator ()(int i);Vec(const Matx<_Tp, cn, 1>& a, const Matx<_Tp, cn, 1>& b, Matx_AddOp);Vec(const Matx<_Tp, cn, 1>& a, const Matx<_Tp, cn, 1>& b, Matx_SubOp);template<typename _T2> Vec(const Matx<_Tp, cn, 1>& a, _T2 alpha, Matx_ScaleOp);
};
//【3】用typedef关键字给---向量类模板----template<typename _Tp, int cn> class Vec//【1】向量模板类Vec的实例化,并且给相应实例的Vec向量模板类实例---指定新的名字//【1】Vec2b--这是一个具体的--类类型---这个类类型实例话的类对象表示如下所示://【1】Vec2b---表示每个Vec2b对象中,可以存储2个char(字符型)数据typedef Vec<uchar, 2> Vec2b; 、//【2】Vec3b---表示每一个Vec3b对象中,可以存储3个char(字符型)数据,比如可以用这样的对象,去存储RGB图像中的一个像素点typedef Vec<uchar, 3> Vec3b;//【3】Vec4b---表示每一个Vec4b对象中,可以存储4个字符型数据,可以用这样的类对象去存储---4通道RGB+Alpha的图像中的像素点typedef Vec<uchar, 4> Vec4b;//【1】Vec2s---表示这个类的每一个类对象,可以存储2个short int(短整型)的数据typedef Vec<short, 2> Vec2s;typedef Vec<short, 3> Vec3s;typedef Vec<short, 4> Vec4s;typedef Vec<ushort, 2> Vec2w;typedef Vec<ushort, 3> Vec3w;typedef Vec<ushort, 4> Vec4w;typedef Vec<int, 2> Vec2i;typedef Vec<int, 3> Vec3i;typedef Vec<int, 4> Vec4i;typedef Vec<int, 6> Vec6i;typedef Vec<int, 8> Vec8i;typedef Vec<float, 2> Vec2f;typedef Vec<float, 3> Vec3f;typedef Vec<float, 4> Vec4f;typedef Vec<float, 6> Vec6f;typedef Vec<double, 2> Vec2d;typedef Vec<double, 3> Vec3d;typedef Vec<double, 4> Vec4d;typedef Vec<double, 6> Vec6d;

至此,opencv中的Vec模板类介绍完毕。

四、Opencv中的宏定义
使用Opencv时常常看到的字母加数字缩写除了Vec模板类,还有就是宏定义了,它经常性的用于Mat的初始化,其具体形式及含义如下:

CV+位深+数据类型缩写+U+通道数目

数据类型缩写有:

S–代表—signed int—有符号整形
U–代表–unsigned int–无符号整形
F–代表–float---------单精度浮点型

其具体含义也就不难理解,CV16UC4就表示16位无符号整型三通道矩阵。
如果我们要使用到Vec类来对使用这种宏定义初始化的Mat赋值时,需要注意Vec类要和宏定义相互对应,像是:

Mat tempImg1(480,640,CV_8UC3);
Vec3b& test = temp.at<Vec3b>(i, j);

由于此处定义的Mat为8位深3通道,所以对应Vec模板类为可容纳3(3通道
个字符型数据(8位)的Vec3b
再如:

Mat tempImg1(480,640,CV_16UC4);
Vec4w& test = temp.at<Vec4w>(i, j);

由于此处定义的Mat为16位深4通道,所以对应Vec模板类为可容纳4个(4通道)无符号整型数据(16位)的Vec4w

参考文献:
C++中类的介绍
C++template模板使用方法
OpenCV 中的 Scalar 类、Vec类
详解 c++ 关键字 explicit

opencv中Vec类的小白向介绍相关推荐

  1. 【6】OpenCV中vec类的介绍

    [1]Vec3f的介绍 Vec3f表示的是3通道float类型的 Vect,就相当于3通道float类型的图像(这是其中一个具体化),解释可以从源代码中看出来. 下面给出一个具体的例子: Vec3f ...

  2. Opencv中Mat类详细解读(学习笔记)

    基于windows10.vs2015.OpenCv4.1.0. 目录 1.Mat类简介 2.Mat类的构造与赋值 2.1.Mat类的构造 2.2.Mat类的赋值 3.Mat类支持的运算 3.1Mat类 ...

  3. opencv中vector类的介绍

    1.c++中vector的用法详解 vector(向量): C++中的一种数据结构,确切的说是一个类.它相当于一个动态的数组,当不知道数组的个数的时候 可以使用vector<int>a; ...

  4. OpenCV中使用类VideoCapture加载视频和打开摄像头

    先直接上示例代码,然后对代码进行讲解. #!/usr/bin/env python # -*- coding: utf-8 -*- # 图像处理开发需求.图像处理接私活挣零花钱,请加微信/QQ 248 ...

  5. 利用opencv中的类FileStorage生成和读取XML和YAML文件

    有时候程序中的变量值.字符串.数组等数据也需要独立于源代码本身保存,这个时候就需要用到XML和YAML文件进行保存. OpenCV4提供了用于生成和读取XML文件和YAML文件的类FileStorag ...

  6. c++ python opencv_ubuntu下C++与Python混编,opencv中mat类转换

    C++ 与 Python 混编 因为赶项目进度,需要使用到深度学习的内容,不过现有的深度学习框架大多使用python代码,对于不会改写C++的朋友来说,需要耗费大量的时间去改写,因此,使用python ...

  7. opencv中Range类的使用

    #include<iostream> #include<opencv2/opencv.hpp> #include<vector> using namespace s ...

  8. OpenCV中Mat类的重载运算符operator()的用法

    图像处理开发需求.图像处理接私活挣零花钱,请加微信/QQ 2487872782 图像处理开发资料.图像处理技术交流请加QQ群,群号 271891601 定义如下: inline Mat Mat::op ...

  9. OpenCV中Mat类的图像如何设置ROI

    Mat类表示的图像进行ROI操作有两种方法 (1)使用拷贝构造函数Mat(constMat& m, const Rect& roi ),矩形roi指定了兴趣区 例如: [cpp] vi ...

最新文章

  1. python用途与前景-Python 未来发展前景怎么样?
  2. 《Drupal实战》——2.5 使用Node clone快速添加测试数据
  3. i5 11300h和R5 5600H 参数对比哪个好
  4. 网站福音 如何免费获得HTTPS认证服务?
  5. 程序=数据结构+算法
  6. 《scikit-learn》SVM(一)
  7. JavaScript学习笔记之原型对象
  8. Android开发之SQLite的使用方法
  9. 搜索引擎技术在仿冒网站检测中的应用
  10. Linux下的时间戳
  11. unix环境高级编程——UNIX体系架构
  12. 机器视觉检测:电阻电容的二次筛选提高效率及达成环保目的
  13. 网络七层协议与网络四层协议
  14. Excel获取目标时间点/日期的方法
  15. 如何用计算机控制三相电机,计算机控制 课程设计 三相步进电机控制.docx
  16. OpenGL入门学习
  17. hex文件格式剖析,以及hex与bin文件互相转换
  18. MacOS深色模式下微信文章页面背景变为黑色问题的解决
  19. 差商matlab编程,Matlab数值计算差商与插值
  20. 拿到一个vue+webpack项目,该如何去看

热门文章

  1. 宝塔面板windows建站教程_WindowsVPS-服务器安装宝塔面板建站教程宝塔面板,
  2. python中width是什么意思_python cv2.resize函数high和width注意事项说明
  3. 钣金展开软件,包能用,无需注册,无需费用,
  4. android源码项目
  5. 网页后缀html、htm、shtml、shtm有什么区别?
  6. 强烈推荐一个下载谷歌浏览器插件的网站!千万别错过!
  7. 求 人工智能及其应用 蔡自兴 徐光佑 版的
  8. Android自己定义TabActivity(实现仿新浪微博底部菜单更新UI)
  9. 2022年申报国家高新技术企业还会抽查吗?
  10. 网络单线复用vlan设置及iptv卡顿看不了直播的解决