Opencv 基础知识详解

Mat类

定义如下:
class CV_EXPORTS Mat
{
public:
//一系列函数
...
/* flag 参数中包含许多关于矩阵的信息,如:
-Mat 的标识
-数据是否连续
-深度
-通道数目
*/
int flags;
//矩阵的维数,取值应该大于或等于 2
int dims;
//矩阵的行数和列数,如果矩阵超过 2 维,这两个变量的值都为-1
int rows, cols;
//指向数据的指针
uchar* data;
//指向引用计数的指针
//如果数据是由用户分配的,则为 NULL
int* refcount;
23//其他成员变量和成员函数
...
};

这里写图片描述

创建 Mat 对象

Mat 是一个非常优秀的图像类,它同时也是一个通用的矩阵类,可以用来创
建和操作多维矩阵。有多种方法创建一个 Mat 对象。

Mat M(3,2, CV_8UC3, Scalar(0,0,255));
cout << “M = ” << endl << ” ” << M << endl;

第一行代码创建一个行数(高度)为 3,列数(宽度)为 2 的图像,图像元
素是 8 位无符号整数类型,且有三个通道。图像的所有像素值被初始化为(0, 0,
255)。由于 OpenCV 中默认的颜色顺序为 BGR,因此这是一个全红色的图像。
第二行代码是输出 Mat 类的实例 M 的所有像素值。
输出:这里写图片描述
常用的构造函数有:
Mat::Mat()
无参数构造方法;
Mat::Mat(int rows, int cols, int type)
创建行数为 rows,列数为 col,类型为 type 的图像;
Mat::Mat(Size size, int type)
创建大小为 size,类型为 type 的图像;
Mat::Mat(int rows, int cols, int type, const Scalar& s)
创建行数为 rows,列数为 col,类型为 type 的图像,并将所有元素初始
化为值 s;
Mat::Mat(Size size, int type, const Scalar& s)
创建大小为 size,类型为 type 的图像,并将所有元素初始化为值 s;
Mat::Mat(const Mat& m)
将 m 赋值给新创建的对象,此处不会对图像数据进行复制, m 和新对象
共用图像数据;
Mat::Mat(int rows, int cols, int type, void* data, size_t step=AUTO_STEP)
创建行数为 rows,列数为 col,类型为 type 的图像,此构造函数不创建
图像数据所需内存,而是直接使用 data 所指内存,图像的行步长由 step
指定。
Mat::Mat(Size size, int type, void* data, size_t step=AUTO_STEP)
创建大小为 size,类型为 type 的图像,此构造函数不创建图像数据所需
内存,而是直接使用 data 所指内存,图像的行步长由 step 指定。
Mat::Mat(const Mat& m, const Range& rowRange, const Range& colRange)
创建的新图像为 m 的一部分,具体的范围由 rowRange 和 colRange 指
定,此构造函数也不进行图像数据的复制操作,新图像与 m 共用图像数
据;
Mat::Mat(const Mat& m, const Rect& roi)
创建的新图像为 m 的一部分,具体的范围 roi 指定,此构造函数也不进
行图像数据的复制操作,新图像与 m 共用图像数据。

矩阵类型 type

其命名规则为CV_(位数)+(数据类型)+(通道数)。具体的有以下值:
这里写图片描述
以CV_8UC1 为例 代表8位无符号型、通道数为1。
这里U(unsigned integer)表示的是无符号整数,S(signed integer)是有符号整数,F(float)是浮点数。

三个特殊矩阵表示

OpenCV 2 中提供了 Matlab 风格的函数,如 zeros(),ones()和 eyes()。
Mat Z = Mat::zeros(2,3, CV_8UC1);
cout << “Z = ” << endl << ” ” << Z << endl;
Mat O = Mat::ones(2, 3, CV_32F);
cout << “O = ” << endl << ” ” << O << endl;
Mat E = Mat::eye(2, 3, CV_64F);
cout << “E = ” << endl << ” ” << E << endl;
这里写图片描述

一些类的向量表示

例如 8U 类型的 RGB 彩色图像可以使用 Vec3b,3 通道 float 类型的矩阵可以
使用 Vec3f。

typedef Vec<uchar, 2> Vec2b;
typedef Vec<uchar, 3> Vec3b;
typedef Vec<uchar, 4> Vec4b;
typedef Vec<short, 2> Vec2s;
typedef Vec<short, 3> Vec3s;
typedef Vec<short, 4> Vec4s;
typedef Vec<int, 2> Vec2i;
typedef Vec<int, 3> Vec3i;
typedef Vec<int, 4> Vec4i;
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;

像素值的读写

at()函数

输出一个白色图片:
Mat img(640,480,CV_8UC1);
for(int i = 0;i< img.rows;i++)
    for(int j = 0;j< img.cols;j++)
        img.at<uchar>(i,j) = 255;
namedWindow("123", WINDOW_NORMAL);
imshow("123", img);
waitKey(0);

遍历图像不建议使用at()函数,可读性高但是效率有点差

使用数据指针

Mat img(640,480,CV_8UC1);
for(int i = 0; i< img.rows; i++)
{
    uchar *p = img.ptr<uchar>(i);
    for(int j = 0; j < img.cols; j++)
        p[j] = (i+j)%255;

}
imshow("123", img);
waitKey(0);

使用指针效率是很高的,但是当程序规模较大,且逻辑复杂时,查找指针错误十分困难。对于不熟悉指针的编程者来说,指针就如同噩梦。如果你对指针使用没有自信,则不建议直接通过指针操作来访问像素。

迭代器

Mat img(640,480,CV_8UC1);
MatIterator_<uchar> start = img.begin<uchar>();
MatIterator_<uchar> end = img.end<uchar>();
for(;start != end; start ++)
{
    *start = 255;
}

例子都是单通道的,多通道的也一个原理

选择感兴趣区域

//创建宽度为 320,高度为 240 的 3 通道图像
Mat img(Size(320,240),CV_8UC3);
//roi 是表示 img 中 Rect(10,10,100,100)区域的对象
Mat roi(img, Rect(10,10,100,100));

除了使用构造函数,还可以使用括号运算符,如下:
Mat roi2 = img(Rect(10,10,100,100));
当然也可以使用 Range 对象来定义感兴趣区域,如下:
//使用括号运算符
Mat roi3 = img(Range(10,100),Range(10,100));

//使用构造函数
Mat roi4(img, Range(10,100),Range(10,100));

Mat_类

Mat_类是对 Mat 类的一个包装,只定义了几个方法,没有定义新的属性。
如果使用 Mat_类,那么就可以在变量声明时确定元素的类型,访问元素时
不再需要指定元素类型,即使得代码简洁,又减少了出错的可能性。

Mat M(600, 800, CV_8UC1);
//在变量声明时指定矩阵元素类型
Mat_<uchar> M1 = (Mat_<uchar>&)M;
for( int i = 0; i < M1.rows; ++i)
{
//不需指定元素类型,语句简洁
37uchar * p = M1.ptr(i);
for( int j = 0; j < M1.cols; ++j )
{
double d1 = (double) (255);
//直接使用 Matlab 风格的矩阵元素读写,简洁
M1(i,j) = d1;
double d2 = M1(i,j);
}

关于Mat_和Mat区别

Point_类、Size_类

对于Point_类不用多言,里面两个成员变量 x,y。
Point_就是 Point2i,也是 Point,Point_就是 Point2f,Point_就是 Point2d。
Size_类成员变量 width、height。Size_就是 Size2i,也是 Size,Size_就是 Size2f。

今天就写到这里吧,以后遇到其他基础知识还会继续添加!

  • 4
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值