opencv的Mat对象

穿精又带淫゛_ 提交于 2020-01-27 14:25:57

IplImage:

在OpenCV中IplImage是表示一个图像的结构体,也是从OpenCV1.0到目前最为重要的一个结构;

在之前的图像表示用IplImage,而且之前的OpenCV是用C语言编写的,提供的接口也是C语言接口;

需要开发者自己分配与管理内存

Mat:

Mat是后来OpenCV封装的一个C++类,用来表示一个图像,和IplImage表示基本一致,但是Mat还添加了一些图像函数;

自动分配孽畜,不存在内存泄漏的问题

在OpenCV中, IplImage 与 Mat是可以相互转换的;

IplImage 转 Mat:

cv::Mat * pmatImage = new cv:Mat( IplImage, 0 ): //第二个参数表示不进行像素数据copy;

Mat 转 IplImage:

IplImage limage = IplImage ( matImage );//不进行数据copy;

 

Mat对象的构造函数

1、Mat::Mat()
无参数构造方法;
2、Mat::Mat(int rows, int cols, int type)
创建行数为 rows,列数为 col,类型为 type 的图像;
3、Mat::Mat(Size size, int type)
创建大小为 size,类型为 type 的图像;
4、Mat::Mat(int rows, int cols, int type, const Scalar& s)
创建行数为 rows,列数为 col,类型为 type 的图像,并将所有元素初始化为值 s;
5、Mat::Mat(Size size, int type, const Scalar& s)
创建大小为 size,类型为 type 的图像,并将所有元素初始化为值 s;
6、Mat::Mat(const Mat& m)
将m赋值给新创建的对象,此处不会对图像数据进行复制,m和新对象共用图像数据,属于浅拷贝;
7、Mat::Mat(int rows, int cols, int type, void* data, size_t step=AUTO_STEP)
创建行数为rows,列数为col,类型为type的图像,此构造函数不创建图像数据所需内存,而是直接使用data所指内存,图像的行步长由 step指定。
8、Mat::Mat(Size size, int type, void* data, size_t step=AUTO_STEP)
创建大小为size,类型为type的图像,此构造函数不创建图像数据所需内存,而是直接使用data所指内存,图像的行步长由step指定。
9、Mat::Mat(const Mat& m, const Range& rowRange, const Range& colRange)
创建的新图像为m的一部分,具体的范围由rowRange和colRange指定,此构造函数也不进行图像数据的复制操作,新图像与m共用图像数据;
10、Mat::Mat(const Mat& m, const Rect& roi)
创建的新图像为m的一部分,具体的范围roi指定,此构造函数也不进行图像数据的复制操作,新图像与m共用图像数据。

 

常用的方法

1.void copyTo(Mat mat)
Mat对象深拷贝

2.void converto(Mat dst,int type)
Mat对象转化函数

3.Mat clone()
Mat对象深拷贝

4.int channels()
获取当前图像的通道数

5.int depth()
获取当前图像的深度

7.ucharptr(i = 0)
获取当前图像的指针

8.Mat zeros(int rows,int cols,int type)
创建全0的Mat对象

 

Mat类存储图像

Mat类是OpenCV里使用广泛的一个类,其中我认为最重要的一个作用就是作为存储图像的数据结构。那么Mat类如何存储的图像呢?

我们都知道图像分为彩色图像和灰度图像,这里我有一个误区,一直认为彩色图像是一种三维矩阵,就是立方体的那种结构,一个图像分为三层。

但是这种理解是错误的,是错误的,是错误的!

其实在存储的图像不管是彩色的还是灰度图像,都是二维的矩阵,具体的存储格式如下

(1)灰度图像的格式:

(2)彩色图像的格式:

看到了吗,虽然彩色图像由BGR三个通道,但是是存储在同一个平面内的,只不过OpenCV在这里把三列才当作一列,因此有img.cols等于图像的列数即图像的像素宽度。

一般我们用Opencv读取的灰度图像的数据类型为uchar类型的,而彩色图像的一个像素的数据类型为<Vec3b>类型的,灰度图一个像素占用1个字节,而彩色图像一个像素3个字节。

接下来就引出了我们如何按像素读取图像呢?

这里主要介绍两种方法,一种非常简单,易于编程,但是效率会比较低;另外一种效率高,但是不太好记。下面依次看代码:

(1)易于编程的

#include <opencv2\core\core.hpp>
#include <opencv2\imgproc\imgproc.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <iostream>
 
using namespace std;
using namespace cv;
 
int main()
{
	Mat img = imread("1.jpg");
	resize(img, img, Size(375, 500));//resize为500*375的图像
	imshow("ori", img);
	for (int i = 0; i < img.rows; i++)
	{
		for (int j = 0; j < img.cols; j++)
		{
			//at<类型>(i,j)进行操作,对于灰度图
			img.at<Vec3b>(i, j)[0] = 255;//对于蓝色通道进行操作
			//img.at<Vec3b>(i, j)[1] = 255;//对于绿色通道进行操作
			//img.at<Vec3b>(i, j)[2] = 255;//对于红色通道进行操作
		}
	}
	imshow("result", img);
	waitKey(0);
	return 0;
}

(2)采用指针对图像进行访问

这里直接写对于彩色图像的操作:

#include <opencv2\highgui\highgui.hpp>
#include <opencv2\imgproc\imgproc.hpp>
#include <opencv2\core\core.hpp>
#include <iostream>
 
using namespace cv;
using namespace std;
int main()
{
    Mat img = imread("1.jpg");
	int rows = img.rows;
	int cols = img.cols * img.channels();
	if(img.isContinuous())//判断是否在内存中连续
	{
		cols = cols * rows;
		rows = 1;
	}
	imshow("ori",img);
	for(int i = 0;i<rows;i++)
	{
		//调取存储图像内存的第i行的指针
		uchar *pointer = img.ptr<uchar>(i);
 
		for(int j = 0;j<cols;j += 3)
		{
			//pointer[j] = 255;//对蓝色通道进行操作
			//pointer[j+1] = 255;//对绿色通道进行操作
			pointer[j+2] = 255;//对红色通道进行操作
		}
	}
	imshow("result",img);
	waitKey();
    return 0;
}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!