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

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;
    在这里插入图片描述
    程序代码见上
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值