03 图像对象的创建与赋值
03 图像对象的创建与赋值
opencv知识点:
- Mat类
- 图像复制的3种方法
- 图像属性的获取
- Mat对象的创建
- Mat对象的赋值
本课所解决的问题:
- Mat是什么?
- Mat对象克隆/拷贝与赋值的区别?
- 如何获取图像的属性?
- 如何创建空白图像?
- 如何对Mat对象赋值?
1.Mat类及其实例
Mat简述
什么是Mat呢,Mat其实就是matrix(矩阵)的缩写
我们看到的图像,就是以数字矩阵的形式存储在计算机中,在opencv中,我们用Mat类的对象
存储图像。
在opencv中,Mat类分为两个部分
- 矩阵头
- 矩阵数据
矩阵头
图像有很多属性。如:大小,**宽和高**,数据类型,**通道数**。这些数据存储在**矩阵头**中
矩阵数据
图像也有很多的数据,图像的数据部分是所有像素的值的一个集合,存储在**矩阵数据**中
Mat对象复制
看上图,我们发现Mat对象复制是有三种方法的
- 克隆
- 拷贝
- 赋值
这里说一下它们的区别
赋值:相当于浅复制,只复制了矩阵头,指向的是同一个数据块。
克隆/拷贝:相当于深复制,还会复制相应的数据块
//1.赋值——浅复制
Mat src = imread("……");
Mat m3 = src;
//2.克隆——深复制
Mat src = imread("……");
Mat m1 = src.clone();
//3.拷贝——深复制
Mat src = imread("……");
Mat m2;
src.copyTo(m2);
Mat对象属性
Mat对象存储了一些属性,如:列数,行数,通道数(维度),位深度,图像类型
怎么获取它们呢?
Mat image= imread("……");
//很简单,通过这些操作即可
image.cols;
image.rows;
image.channels();
image.depth();
image.type();
数据类型和通道数
图像的数据类型type
由两部分组成
- 类型
- 通道数
在opencv中type是枚举类型的数值
如CV_8UC3
:表示 8位无符号整数(字节类型)三通道。枚举数值16
![41102c810a9e4269a06853b32be428c6](https://picture0717.oss-cn-beijing.aliyuncs.com/img/41102c810a9e4269a06853b32be428c6.png)
忽略掉前面的字符,我们只关注Cx,可以很快的发现,Cx即表示通道数channels
。
如C1——单通道,C2——双通道……
注意
- 当为单通道时,
C1
可以省略,直接为CV_8U
- 单通道为灰度图像,三通道为彩色图像
深度
图像深度depth
和数据类型关联密切,其在opencv
中也为枚举数值。
![e81ce226ddeb484aaed1d1a9c8f25d21](https://picture0717.oss-cn-beijing.aliyuncs.com/img/e81ce226ddeb484aaed1d1a9c8f25d21.png)
图像深度有真实值和枚举值之分。
- 枚举值
图像depth的枚举值跟通道数无关,相同类型下如CV_8UC1
和CV_8UC3
,图像深度的枚举值是一样的
- 真实值
图像depth的真实值还要考虑通道数,如CV_8UC3
的通道数为 8*3=24位
2.Mat对象的创建
Mat对象创建,常用的是创建空白图像。如下演示了三种方法
方法一:
Mat src = imread("……");
Mat m4 = Mat::zeros(src.size(),src.type())
/*
矩阵填充0
行列为src行列
数据类型为src的数据类型
*/
方法二:
Mat src = imread("……");
Mat m5 = Mat::zeros(Size(512,512),CV_8UC3);
/*
矩阵填充0
行列为512*512
数据类型为CV_8UC3(8UC指8位无符号字符,3指3个通道)
*/
方法三:
Mat src = imread("……");
Mat m6 = Mat::ones(Size(512,512),CV_8UC3);
/*
矩阵填充1
其余与上相同
*/
C11创建图像的新方式
Mat kernel = (Mat_<char>(3,3)<<0,-1,0,-1,5,-1,0,-1,0);
3.Mat对象的赋值
只会创建图像是不够的,这里我们再说一下Mat对象赋值的事情
常用的有4种方法
-
Mat::zeros()
-
Mat::ones();
-
=
-
Scalar
完整代码放在前面
//函数定义
void mat_creation_demo(Mat& image);
//函数实现
void QuickDemo::mat_creation_demo(Mat& image) {
//创建空白图像
Mat m = Mat::zeros(Size(8, 8), CV_8UC1);
//Mat m = Mat::zeros(Size(8, 8), CV_8UC3);
//Mat m = Mat::ones(Size(8, 8), CV_8UC1);
//Mat m = Mat::ones(Size(8, 8), CV_8UC3);
//m=127;
//m=Scalar(127,127,127);
std::cout << m << std::endl;//为了说明以上语句的不同,我们把矩阵进行打印
}
现在开始分别说明:
Mat::zeros
Mat m = Mat::zeros(Size(8, 8), CV_8UC1);
Mat m = Mat::zeros(Size(8, 8), CV_8UC3);
矩阵宽度 = 图像的列 * 通道数
当为CV_8UC1
时,单通道,矩阵宽度8
![](https://picture0717.oss-cn-beijing.aliyuncs.com/img/c03c125f20bccec34df991fe86694b1.png)
当为CV_8UC3
时,三通道,矩阵宽度24
程序:
main.cpp
using namespace cv;
using namespace std;
int main(int argc, char** argv) {
Mat src = imread("C:/Users/LZQ/Desktop/lena.png"); // B, G, R
if (src.empty()) {
printf("could not load image....\n");
return -1;
}
imshow("输入窗口", src);
QuickDemo qd;
qd.mat_creation_demo();
waitKey(0);
destroyAllWindows();
return 0;
}
quickopencv.h
#pragma once
#include <opencv2/opencv.hpp>
using namespace cv;
class QuickDemo { //快速的演示文件 class类
public:
// void colorSpace_Demo(Mat& image); //02
void mat_creation_demo();
};
CV_8UC1
quickdemo.cpp
void QuickDemo::mat_creation_demo() {
Mat m3 = Mat::zeros(Size(8, 8), CV_8UC1);
std::cout << m3 << std::endl; //std::是名称空间,指的是std里面的cout函数
}
CV_8UC3
保持其余的程序不变,修改quickdemo.cpp
quickdemo.cpp
void QuickDemo::mat_creation_demo() {
Mat m3 = Mat::zeros(Size(8, 8), CV_8UC1);
std::cout << m3 << std::endl; //std::是名称空间,指的是std里面的cout函数
}