OpenCV笔记3-Mat对象

1 Mat对象与IplImage对象

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

2 Mat组成部分

  • Mat有两个必不可少的组成部分:一个头部和一个数据块
  • 头部:包含了矩阵的所有相关信息(大小、通道数量、数据类型等)
  • 数据块:包含了图像中所有像素的值
  • 头部有一个指向数据块的指针,即data属性
  • cv::Mat有一个很重要的属性,即只有在明确要求时,内存块才会被复制。实际上,大多数操作仅仅复制了cv::Mat的头部,因此多个对象会指向同一个数据块

3 Mat对象构造函数与常用方法

3.1 对象构造函数

  • Mat():无参构造方法
  • Mat(int rows, int cols, int type):创建行数为rows,列为col,类型为type的图像(图像元素类型,如CV_8UC3等)
  • Mat(Size size, int type):创建大小为size,类型为type的图像
  • Mat(int rows, int cols, int type, const Scalar &s):创建行数为 rows,列数为 col,类型为 type 的图像,并将所有元素初始化为值 s
  • Mat(Size size, int type, const Scalar &s):创建大小为 size,类型为 type 的图像,并将所有元素初始化为值 s
  • Mat(int ndims, const int *sizes, int type):构造n维矩阵
  • Mat(int ndims, const int *size, int type, const Scalar &s):构造n维矩阵并初始化为值s

3.2 常用方法

  • void copyTo(Mat mat)
  • void convertTo(Mat dst, int type)
  • Mat clone()
  • int channels()
  • int depth()
  • bool empty()
  • uchar* ptr(i = 0)

4 Mat对象使用

4.1 复制

  • 部分复制:一般情况下只会复制Mat对象的头和指针部分,不会复制数据部分
Mat A = imread(imgFilePath);
Mat B(A);	//初始化对象,只复制头部和指针部分
  • 完全复制:如果想把Mat对象的头部和数据部分一起复制,可以通过如下两个API实现
//方法1
Mat F = A.clone();
//方法2
Mat G;
A.copyTo(G);

4.2 Mat对象使用-四个要点

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

4.3 Mat对象创建

  • cv::Mat::Mat构造函数
    Mat M(2, 2, CV_8UC3, Scalar(0, 0, 255))
    • 前两个参数分别表示行(row)跟列(column)
    • 第三个参数CV_8UC3中的8表示每个通道占8位、U表示无符号、C表示Char类型、3表示通道数目是3(RGB图像)
    • 第四个参数是向量表示初始化每个像素值是多少,向量长度对应通道数目一致
  • 创建多维数组cv::Mat::create
int sz[3] = {2, 2, 2};
Mat L(3, sz, CV_8UC1, Scalar::all(0));
  • cv::Mat::create实现
Mat M;
M.create(4, 3, CV_8UC2);
M = Scalar(127, 127);
cout << "M = " << endl << M << endl;
uchar* firstRow = M.ptr<uchar>(0);
printf("%d", *firstRow);
  • 定义小数组
Mat C = (Mat_<double>(3,3) << 0,-1,0,-1,5,-1,0,-1,0);
cout << "C = " << endl << C << endl;

5 代码

  • 头文件
#include<opencv2/opencv.hpp>
#include<iostream>

using namespace std;
using namespace cv;
  • 读取图像,显示图像(原图)
	Mat src;	//定义一个Mat对象
	src = imread("D:/C++project/OpenCVProject/test.jpg");
	if (src.empty()) {
		cout << "could not load image..." << endl;
		return -1;
	}
	namedWindow("My image", WINDOW_AUTOSIZE);
	imshow("my image", src);

在这里插入图片描述

  • Scalar使用
	Mat dst;
	dst = Mat(src.size(), src.type());	//使用Mat的构造函数
	dst = Scalar(127, 0, 255);
	namedWindow("output", WINDOW_AUTOSIZE);
	imshow("output", dst);

在这里插入图片描述

  • 复制
//方法1
	Mat dst = src.clone();	//完全拷贝
	namedWindow("output", WINDOW_AUTOSIZE);
	imshow("output", dst);
//方法2
	Mat dst;	
	src.copyTo(dst);		//复制
	namedWindow("output", WINDOW_AUTOSIZE);
	imshow("output", dst);
  • 通道数、行数、列数
	cvtColor(src, dst, COLOR_BGR2GRAY);		//转换色彩空间,从BGR转换到灰度
	printf("input image channels : %d\n", src.channels());	//转换前的通道数,即RGB的通道数
	printf("output image channels : %d\n", dst.channels());	//转换后的通道数,即灰度图像的通道数
	
	int cols = dst.cols;		//cols为列数(columns)
	int rows = dst.rows;		//rows为行数(rows)
	printf("rows : %d cols : %d\n", rows, cols);
	const uchar* firstRow = dst.ptr<uchar>(0);	//指向第一个像素的指针,获取第0个的像素点灰度值
	printf("first pixel value : %d", *firstRow);	//firstRow是一个指针

在这里插入图片描述
在这里插入图片描述

  • 构造函数
	//可以先用小的图像来验证算法的正确性,然后再应用到大的图像中
	Mat M(3, 3, CV_8UC3, Scalar(0,0,255));	//定义一个3*3的三通道矩阵
	cout << "M = " << endl << M << endl;

	Mat M1(100, 100, CV_8UC1, Scalar(127));	//创建一个一通道的灰度图像
	namedWindow("output", WINDOW_AUTOSIZE);
	imshow("output", M1);

在这里插入图片描述
在这里插入图片描述

  • create函数
	Mat m1;
	m1.create(src.size(), src.type());	//创造一个与src相同大小图像
	m1 = Scalar(0, 0, 255);				//表示红色
	namedWindow("output", WINDOW_AUTOSIZE);
	imshow("output", m1);

在这里插入图片描述

  • zeros函数和eye函数
	//元素点像素值为全0,表示纯黑色的图片,与输入图像大小一致
	Mat m2 = Mat::zeros(src.size(), src.type());	
	namedWindow("output", WINDOW_AUTOSIZE);
	imshow("output", m2);

	Mat m3 = Mat::zeros(2, 2, CV_8UC1);
	cout << "m3 = " << endl << m3 << endl;

	Mat m4 = Mat::eye(2, 2, CV_8UC1);
	cout << "m4 = " << endl << m4 << endl;

在这里插入图片描述
在这里插入图片描述
【注】

  • 在RGB系统中,图像是这样存储的:(注意是BGR的形式)
    在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/CC_monster/article/details/86650154