OpenCV-图像处理(03、Mat对象)

版权声明:本文由 Micheal 超 博客 创作,转载请附带链接,有问题欢迎交流。 https://blog.csdn.net/qq_42887760/article/details/85784903

Mat对象与IplImage对象

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

Mat对象使用

  • Mat对象构造函数

构造函数(部分常用的) 说明
Mat(); 无参构造方法
Mat(int rows, int cols, int type); 创建行数为rows,列数为cols,类型为type的图像
Mat(Size size, int type); 创建大小为size,类型为type的图像
Mat(int rows, int cols, int type, const Scalar& s); 创建行数为rows,列数为cols,类型为type的图像,并且将所有元素初始化为s
Mat(Size size, int type, const Scalar& s); 创建大小为size,类型为type的图像,并且将所有元素初始化为值s
Mat(int ndims, const int* sizes, int type);
Mat(int ndims, const int* sizes, int type, const Scalar& s);
Mat(const Mat& m) 将m赋值给新创建的对象,此处不会对图像数据进行复制,m和新对象共用图像数据

其中:type可以是:CV_8UC1、CV_16SC1、… … 、CV_64FC3 等。C[The channel number]、U(unsigned integer)表示的是无符号整数,S(signed integer)是有符号整数, F(float)是浮点数。
里面的 8U 表示8位无符号整数(0 ~ 255),16S 表示16位有符号整数(-32768 ~ 32767),64F 表示64位浮点 double数据类型,C后面的数表示通道数,例如:C1表示一个通道数的图像,C3表示3通道图像,以此类推。

#include<opencv2/opencv.hpp>
#include<iostream>
#include<math.h>

using namespace std;
using namespace cv;

int main(int argc,char** argv){
	Mat src;
	src=imread("E:/Experiment/OpenCV/Pictures/dog2.jpg");
	if(!src.data){
		cout<<"Could not load image ... "<<endl;
		return -1;
	}

	//构造函数示例
	Mat dst1(250,250,CV_8UC1);//创建200行200列类型为8位单通道矩阵
	Mat dst2(Size(250,250),CV_8UC3);//创建300行400列类型为8位3通道矩阵

	// CV_8UC1 8表示8位,UC表示unsigned char,1表示1个通道, Scalar表示向量长度,要与通道数目一致
    Mat dst3(300, 300, CV_8UC3, Scalar(0, 0, 255));//3*3个像素点,CV_8UC3表示像素点为三个通道颜色数据,CV_8UC1表示像素点为单通道,对应的传 Scalar(255) 
	Mat dst4(Size(300,300),CV_8UC1,Scalar(127));//500*500个像素点,CV_32FC2表示32位浮点型数据,2通道图像,127表示灰色
	
	Mat dst5(src);//将src赋值给dst1,共用数据对象

	Mat dst6 = Mat(src.size(), src.type());
    dst6 = Scalar(127, 0, 255);//给矩阵所有的像素点设置颜色数据,绯红,这里的 = 号运算符重载了。Scalar参数顺序是 B G R
        


	namedWindow("input",CV_WINDOW_AUTOSIZE);
	imshow("input",src);

	namedWindow("output1",CV_WINDOW_AUTOSIZE);
	imshow("output1",dst1);

	namedWindow("output2",CV_WINDOW_AUTOSIZE);
	imshow("output2",dst2);

	namedWindow("output3",CV_WINDOW_AUTOSIZE);
	imshow("output3",dst3);

	namedWindow("output4",CV_WINDOW_AUTOSIZE);
	imshow("output4",dst4);

	namedWindow("output5",CV_WINDOW_AUTOSIZE);
	imshow("output5",dst5);

	namedWindow("output6",CV_WINDOW_AUTOSIZE);
	imshow("output6",dst6);

	waitKey(0);

	return 0;
}

运行截图:
在这里插入图片描述
在这里插入图片描述

  • Mat对象常用方法

函数 功能
row 行数
col 列数
rowRange 为指定的行span创建一个新的矩阵头,可去指定行区间元素
colRange 为指定的列span创建一个新的矩阵头,可去指定列区间元素
Mat clone() 创建一个数组及其基础数据的完整副本
void copyTo(Mat mat) 完全复制一份
void convertTo(Mat dst, int type) 转换,比如8位的转换为float
int channels() 通道数
int depth() 深度
bool empty(); 是否空,如果数组没有elements,则返回true
uchar* ptr(i=0) 矩阵数据指针
Mat::zeros 返回指定大小和类型的0数组
Mat::ones 返回一个指定的大小和类型全为1的数组
Mat::at 返回对指定数组元素的引用
#include<opencv2/opencv.hpp>
#include<iostream>
#include<math.h>
using namespace std;
using namespace cv;

int main(int argc,char** argv){
	Mat src;
	src=imread("E:/Experiment/OpenCV/Pictures/dog2.jpg");
	if(src.empty()){
		cout<<"Could not laod image ..."<<endl;
		return -1;
	}
	//图片的复制操作
	Mat dst1=src.clone();//完全拷贝
	Mat dst2; 
	src.copyTo(dst2);//完全拷贝
	Mat dst3(src);//只是复制部分,Mat对象头部与数据的指针,不会复制数据

	namedWindow("input",CV_WINDOW_AUTOSIZE);
	imshow("input",src);

	namedWindow("output1",CV_WINDOW_AUTOSIZE);
	imshow("output1",dst1);

	namedWindow("output2",CV_WINDOW_AUTOSIZE);
	imshow("output2",dst2);

	namedWindow("output3",CV_WINDOW_AUTOSIZE);
	imshow("output3",dst3);

	
	//其他函数测试
	Mat dst4;//测试channels()、ptr()、cols()、rows();
	cvtColor(src, dst4, CV_BGR2GRAY);//dst4对象输出图像的内存是自动分配的
    printf("rgb.channels=%d, gray.channels=%d,src.type=%d,dst4.type=%d\n", src.channels(), dst4.channels(), src.type(), dst4.type());//rgb通道数为3,gray通道数为1,16,0

    const uchar* firstRow = dst4.ptr<uchar>(0);//图像第一行颜色数据
    printf("first pixel value : %d\n", *firstRow);
    printf("dst.cols=%d, dst.rows=%d\n\n", dst4.cols, dst4.rows);


    // CV_8UC1 8表示8位,UC表示unsigned char,1表示1个通道, Scalar表示向量长度,要与通道数目一致
    Mat dst5(3, 3, CV_8UC3, Scalar(0, 0, 255));//3*3个像素点,CV_8UC3表示像素点为三个通道颜色数据,CV_8UC1表示像素点为单通道,对应的传 Scalar(255) 
    cout << "dst5 = " << endl << dst5 << endl<<endl;//打印每个通道颜色数据
										/*  m =
												[  0, 0, 255,   0, 0, 255,   0, 0, 255;
												   0, 0, 255,   0, 0, 255,   0, 0, 255;
												   0, 0, 255,   0, 0, 255,   0, 0, 255 ]
										*/
    imshow("scalar", dst5);


    Mat dst6;
    dst6.create(src.size(), src.type());//以create方式创建Mat
    dst6 = Scalar(0, 0, 255);//Scalar参数顺序是 B G R
    imshow("create", dst6);
    //Mat kernel = (Mat_<char>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0); //定义小数组,以 << 运算符重载 创建Mat
    Mat zeros = Mat::zeros(2, 2, CV_8UC1);//初始值0
    cout << "zeros = " << endl << zeros << endl<<endl;
    /*
        zeros =
            [0,   0;
             0,   0]
        eye =
            [1,   0;
             0,   1;
             0,   0]
    */
    Mat eye = Mat::eye(3, 2, CV_8UC1);//沿着主对角线的像素点(不是通道)的第一个通道的数据设置为1,其他都为0,对于CV_8UC1的方阵可以生成单一矩阵
    cout << "eye = " << endl << eye << endl;


	waitKey(0);

	return 0;
}

运行截图:
在这里插入图片描述
在这里插入图片描述

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

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

Mat定义数组

  • cv::Mat构造函数
    Mat M(2,2,CV_8UC3, Scalar(0,0,255))
    其中前两个参数分别表示行(row)跟列(column)、第三个CV_8UC3中的8表示每个通道占8位、U表示无符号、C表示Char类型、3表示通道数目是3,第四个参数是向量表示初始化每个像素值是多少,向量长度对应通道数目一致

  • 创建多维数组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 << endl;
uchar* firstRow = M.ptr(0);
printf(”%d", *firstRow);

在这里插入图片描述

  • 定义小数组
    Mat C = (Mat_(3,3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
    cout << "C = " << endl << " " << C << endl << endl;
    在这里插入图片描述
    程序代码见上

猜你喜欢

转载自blog.csdn.net/qq_42887760/article/details/85784903