四、opencv中图像、Mat类、矩阵关系

四、opencv中图像、矩阵、Mat类

4.1 图像和矩阵

图像中的每个点称为像素,每个像素可以存储一个或多个值,这个取决于它是否为彩色,灰色,黑色或者白色图像(也称为二进制图像)。

灰度级尺度图像可以存储一个值,彩色图像可以存储三个值。这些值通常是介于0-255之间的整数。

在计算机中,我们将图像以矩阵的格式存储,在矩阵格式中,每个像素都有位置,可以通过列数和行数引用到像素,opencv中通过Mat类来实现图像数据的管理

在这里插入图片描述

下图显示的是使用一个宽度x高度x颜色数目矩阵的彩色图像和使用一个单一矩阵的灰度图像(在opencv中这些矩阵都可以使用Mat类来创建)

在这里插入图片描述

Mat类不只是用于存储图像,而且还可以存储任意大小的不同类型的矩阵。可以使用它作为代数矩阵,并执行操作。

计算机内存中矩阵是如何存储的?

在内存中,矩阵被保存为数组或值按列和行有序排序的序列。

​ 下表显示BGR图像格式中的像素序列

在这里插入图片描述

按此顺序,通过下面公式就可以访问任何像素:

value = Row_i * num_cols * num_channels + col_i + channel_i
值    = 行号   * 每行列数  * 每列像素个数   + 第几列 + 第几个像素

4.2 Mat类和矩阵矩阵

1、Mat对象与IplImage对象

  • Mat对象OpenCV2.0之后引进的图像数据结构、自动分配内存、不存在内存泄漏的问题,是面向对象的数据结构。分了两个部分,头部与数据部分
  • IplImage是从2001年OpenCV发布之后就一直存在,是C语言风格的数据结构,需要开发者自己分配与管理内存,对大的程序使用它容易导致内存泄漏问题

2、Mat对象构造函数

Mat类是一个图像类,也是一种通用矩阵类。下面先了解一下Mat构造矩阵和操作矩阵的一些方法

//构造函数
//无参构造
Mat::Mat();
//创建行数为rows,列为col,类型为type的图像(图像元素类型,如CV_8UC3等)
Mat::Mat(int rows, int cols, int type);
//创建大小为size,类型为type的图像
Mat::Mat(Size size, int type);
//创建行数为rows,列数为 col,类型为 type 的图像,并将所有元素初化为值s
Mat::Mat(int rows, int cols, int type, const Scalar& s);
//创建大小为size,类型为type的图像,并且将所有元素初始化为值s 
Mat(Size size, int type, const Scalar& s); 
//ndims是维数。 
Mat(int ndims, const int* sizes, int type); 
//ndims是维数。 
Mat(int ndims, const int* sizes, int type, const Scalar& s); 
//拷贝构造函数,仅复制头和指针,不复制数据部分,即共用数据部分 
Mat(const Mat& m);

3、Mat对象使用要点

  1. 输出图像的内存是自动分配的
  2. 使用OpenCV的C++接口,不需要考虑内存分配问题
  3. 赋值操作和拷贝构造函数只会复制头部分
  4. 使用clone与copyTo两个函数实现数据完全复制

43 Mat对象创建矩阵

创建矩阵需要知道矩阵的尺寸大小和数据类型;

矩阵尺寸大小:就是m行n列;Size(5,5);

矩阵数据类型:深度8/32位,类型uchar/float,通道数1/3/4;

可选的矩阵的数据类型:

CV_8UC1 // 8位无符号单通道

CV_8UC3 // 8位无符号3通道

CV_8UC4 // 8位无符号4通道

CV_32FC1 // 32位浮点型单通道

CV_32FC3 // 32位浮点型3通道

CV_32FC4 // 32位浮点型4通道

如:Mat b = Mat(Size(5, 5), CV_8UC1);

创建3通道的2行2列的矩阵

/*
2,2:分别表示行(row)跟列(column)、
CV_8UC3:中的8表示每个通道占8位、U表示无符号、C表示Char类型、3表示通道数目是3
Scalar(0,0,255):是向量表示初始化每个像素值是多少,向量长度对应通道数目一致
*/
//创建3通道的2行2列的矩阵,(0,0,255)为1列中的三个元素
Mat M1(2,2,CV_8UC3, Scalar(0,0,255));
cout << "M1 = " << endl << " " << M1 << endl << endl;

在这里插入图片描述

创建3通道,4行3列的矩阵

//创建3通道,4行3列的矩阵
Mat M2;
M2.create(4, 3, CV_8UC2);
M2 = Scalar(127,127);
cout << "M2 = " << endl << " " << M2 << endl << endl;
uchar* firstRow = M2.ptr<uchar>(0);
cout << "firstRow = " << firstRow << endl;

在这里插入图片描述

创建1通道的3行3列的矩阵

 //创建1通道的3行3列的矩阵。赋值为下面的数
 Mat M3 = (Mat_<double>(3,3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
 cout << "M3 = " << endl << " " << M3 << endl << endl;

在这里插入图片描述

4.4 矩阵的初始化

Mat mz = Mat::zeros(5, 5, CV_8UC1);	//全0矩阵
Mat mo = Mat::ones(5, 5, CV_8UC1);	//全1矩阵
Mat me = Mat::eye(5, 5, CV_32FC1);	//对角线为1的对角矩阵

cout << "mz = " << endl << mz << endl;
cout << "mo = " << endl << mo << endl;
cout << "me = " << endl << me << endl;

在这里插入图片描述

4.5 案例代码

创建Qt工程参考2.2章-Qt测试Opencv代码

在Qt工程的pro文件添加如下内容

#若将D:/opencv/install/install/include添加到环境变量,下面INCLUDEPATH这三行可以不写
INCLUDEPATH += D:/opencv/install/install/include/opencv \
            D:/opencv/install/install/include/opencv2  \
            D:/opencv/install/install/include

LIBS += -L D:/opencv/install/install/x64/mingw/lib/libopencv_*.a

#添加环境变量之后可以不使用绝对路径
#LIBS += -L libopencv_*.a

修改Qt工程的main.cpp文件如下

#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/objdetect/objdetect.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
using namespace std;
using namespace cv;
int main()
{
    //创建3通道的2行2列的矩阵,(0,0,255)为1列中的三个元素
    Mat M1(2,2,CV_8UC3, Scalar(0,0,255));
    cout << "M1 = " << endl << " " << M1 << endl << endl;

    //创建3通道的4行3列的矩阵,(127,127)为1列中的2个元素
    Mat M2;
    M2.create(4, 3, CV_8UC2);
    M2 = Scalar(127,127);
    cout << "M2 = " << endl << " " << M2 << endl << endl;
    
    
    uchar* firstRow = M2.ptr<uchar>(0);     //指针指向矩阵的第一行
    printf("%d\n", *firstRow);                //取指针的内容(本质就是取到第一个元素)

    //创建1通道的3行3列的矩阵。赋值为下面的数
    Mat M3 = (Mat_<double>(3,3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
    cout << "M3 = " << endl << " " << M3 << endl << endl;
    
    
    Mat mz = Mat::zeros(5, 5, CV_8UC1);	//全0矩阵
    Mat mo = Mat::ones(5, 5, CV_8UC1);	//全1矩阵
    Mat me = Mat::eye(5, 5, CV_32FC1);	//对角线为1的对角矩阵
    
    cout << "mz = " << endl << mz << endl;
    cout << "mo = " << endl << mo << endl;
    cout << "me = " << endl << me << endl;
}

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值