opencv的Mat类基本操作
2017-09-11 15:47
399 查看
官方对mat介绍的原话:
The class Mat represents an n-dimensional dense numerical single-channel or multi-channel array. It can be used to store real or complex-valued vectors
and matrices, grayscale or color images, voxel volumes, vector fields, point clouds, tensors, histograms (though, very high-dimensional histograms may be better stored in a SparseMat
译文:Mat类用于表示一个多维的单通道或者多通道的稠密数组。能够用来保存实数或复数的向量、矩阵,灰度或彩色图像,立体元素,点云,张量以及直方图(高维的直方图使用SparseMat保存比较好)。简而言之,Mat就是用来保存多维的矩阵的.
opencv2的Mat类带来的改变:
1不必手动开辟空间 2不必再在不需要的时候立即将空间释放
Mat由两个数据部分组成:矩阵头(包含矩阵尺寸、存储方法、存储地址等信息)和一个指向存储所有像素值的矩阵的指针。
问题:关于图像拷贝问题?
OpenCV使用引用计数机制来解决复制图像的问题。其思路是让每个
Mat 对象有自己的信息头,但共享同一个矩阵。这通过让矩阵指针指向同一地址而实现。而拷贝构造函数则只拷贝信息头和矩阵指针 ,而不拷贝矩阵。
以上代码中的所有Mat对象最终都指向同一个也是唯一一个数据矩阵。
如果想让各自对象都有一个信息头和矩阵,这时候可以使用cone()和copyTo()两个成员函数。
问题:如何创建ROI?
你可以创建只引用部分数据的信息头。比如想要创建一个感兴趣区域(
ROI ),你只需要创建包含边界信息的信息头。
其中Range()指定感兴趣行或列的范围,Range指从起始索引到终止索引(不包括终止索引)的一连续序列。
问题:图像的存储方式
存储像素值需要指定颜色空间和数据类型。
常用的颜色空间:RGB HSV HLS 灰度级空间 等。
Mat和Matlab里的数组格式有点像,但一般是二维向量,如果是灰度图,一般存放<uchar>类型;如果是RGB彩色图,存放<Vec3b>类型。
单通道灰度图数据存放格式:
多通道的图像中,每列并列存放通道数量的子列,如RGB三通道彩色图:
注意通道的顺序反转了:BGR。通常情况内存足够大的话图像的每一行是连续存放的,也就是在内存上图像的所有数据存放成一行,这中情况在访问时可以提供很大方便。可以用 isContinuous()函数来判断图像数组是否为连续的。
问题:如何访问图像中的像素
访问图像中像素的三个方法:
1.指针访问:c操作符[]
2.迭代器iterator
3.动态地址计算
三种方法在访问速度上有差异
第一种:用指针访问 访问速度最快
void colorreduce(Mat& inputImage,Mat& outputImage,int div)
{
outputImage=inputImage.clone();
int rowNumber=outputImage.rows;
int colNumber=outputImage.cols*outputImage.channels();//每一行元素的个数
for(int i=0;i<rowNumber;i++)
{
uchar* data=outputImage.ptr<uchar>(i);
//uchar* data=outputImage.ptr<uchar>(i)[j];//获取第i行第j列元素的值
fo
f497
r(int j=0;j<colNumber;j++)
{
data[j] = data[j] / div*div + div / 2;
}
//*data++ = *data / div*div + div / 2; //所有方法中最快的
}
第二种:用迭代器操作像素
这里,我们只需要获取图像矩阵的begin和end,然后增加迭代直至从begin到end。将*操作符添加到迭代指针前,即可访问当前指向的内容。相比指针容易产生越界的情况,迭代器是绝对安全的
void colorReduce(Mat& inputImage,Mat& outputImage,int div)
{
outputImage = inputImage.clone();
Mat_<Vec3b>::iterator it = outputImage.begin<Vec3b>();
Mat_<Vec3b>::iterator itend = outputImage.end<Vec3b>();
for (; it != itend; ++it)
{
(*it)[0] = (*it)[0] / div*div + div / 2;
(*it)[1] = (*it)[1] / div*div + div / 2;
(*it)[2] = (*it)[2] / div*div + div / 2;
}
第三种:动态地址计算
void colorReduce(Mat& inputImage,Mat& outputImage,int div)
{
outputImage = inputImage.clone();
int rowNumber = outputImage.rows;
int colNumber = outputImage.cols;
for (int i = 0; i < rowNumber; i++)
{
for (int j = 0; j < colNumber; j++)
{
outputImage.at<Vec3b>(i,j)[0]=
outputImage.at<Vec3b>(i,j)[0]/div*div+div/2;
outputImage.at<Vec3b>(i,j)[1]=
outputImage.at<Vec3b>(i,j)[1]/div*div+div/2;
outputImage.at<Vec3b>(i,j)[2]=
outputImage.at<Vec3b>(i,j)[2]/div*div+div/2;
}
}
}
问题:如何显式地创建一个Mat对象
Mat 不但是一个很赞的图像容器类,它同时也是一个通用的矩阵类,所以可以用来创建和操作多维矩阵。创建一个Mat对象有多种方法:
一:Mat() 构造函数
显示结果:
Scalar 是个short型vector。指定这个能够使用指定的定制化值来初始化矩阵.
二:Create()
结果:
这个创建方法不能为矩阵设初值,它只是在改变尺寸时重新为矩阵数据开辟内存
三:MATLAB形式的初始化方式:
zeros(),
ones(), :eyes() 。使用以下方式指定尺寸和数据类型:
结果:
mat的常见属性
1:data uchar型的指针。Mat类分为了两个部分:矩阵头和指向矩阵数据部分的指针,data就是指向矩阵数据的指针
2:dims 矩阵的维度,例如5*6矩阵是二维矩阵,则dims=2,三维矩阵dims=3.
3:rows 矩阵的行数
4:cols 矩阵的列数
5:size 矩阵的大小,size(cols,rows),如果矩阵的维数大于2,则是size(-1,-1)
6:channels 矩阵元素拥有的通道数
7:type 表示了矩阵中元素的类型以及矩阵的通道个数,它是一系列的预定义的常量,其命名规则为CV_(位数)+(数据类型)+(通道数)。具体的有以下值:
8:depth 矩阵中元素的一个通道的数据类型,这个值和type是相关的。例如 type为 CV_16SC2,一个2通道的16位的有符号整数。那么,depth则是CV_16S。depth也是一系列的预定义值,
关于使用data访问图像中像素的一些问题:http://blog.csdn.net/zy122121cs/article/details/47029431
The class Mat represents an n-dimensional dense numerical single-channel or multi-channel array. It can be used to store real or complex-valued vectors
and matrices, grayscale or color images, voxel volumes, vector fields, point clouds, tensors, histograms (though, very high-dimensional histograms may be better stored in a SparseMat
译文:Mat类用于表示一个多维的单通道或者多通道的稠密数组。能够用来保存实数或复数的向量、矩阵,灰度或彩色图像,立体元素,点云,张量以及直方图(高维的直方图使用SparseMat保存比较好)。简而言之,Mat就是用来保存多维的矩阵的.
opencv2的Mat类带来的改变:
1不必手动开辟空间 2不必再在不需要的时候立即将空间释放
Mat由两个数据部分组成:矩阵头(包含矩阵尺寸、存储方法、存储地址等信息)和一个指向存储所有像素值的矩阵的指针。
问题:关于图像拷贝问题?
OpenCV使用引用计数机制来解决复制图像的问题。其思路是让每个
Mat 对象有自己的信息头,但共享同一个矩阵。这通过让矩阵指针指向同一地址而实现。而拷贝构造函数则只拷贝信息头和矩阵指针 ,而不拷贝矩阵。
Mat A, C; // 只创建信息头部分 A = imread(argv[1], CV_LOAD_IMAGE_COLOR); // 这里为矩阵开辟内存 Mat B(A); // 使用拷贝构造函数 C = A; // 赋值运算符
以上代码中的所有Mat对象最终都指向同一个也是唯一一个数据矩阵。
如果想让各自对象都有一个信息头和矩阵,这时候可以使用cone()和copyTo()两个成员函数。
Mat F = A.clone(); Mat G; A.copyTo(G);
问题:如何创建ROI?
你可以创建只引用部分数据的信息头。比如想要创建一个感兴趣区域(
ROI ),你只需要创建包含边界信息的信息头。
Mat D (A, Rect(10, 10, 100, 100) ); // using a rectangle Mat E = A(Range:all(), Range(1,3)); // using row and column boundariesq
其中Range()指定感兴趣行或列的范围,Range指从起始索引到终止索引(不包括终止索引)的一连续序列。
问题:图像的存储方式
存储像素值需要指定颜色空间和数据类型。
常用的颜色空间:RGB HSV HLS 灰度级空间 等。
Mat和Matlab里的数组格式有点像,但一般是二维向量,如果是灰度图,一般存放<uchar>类型;如果是RGB彩色图,存放<Vec3b>类型。
单通道灰度图数据存放格式:
多通道的图像中,每列并列存放通道数量的子列,如RGB三通道彩色图:
注意通道的顺序反转了:BGR。通常情况内存足够大的话图像的每一行是连续存放的,也就是在内存上图像的所有数据存放成一行,这中情况在访问时可以提供很大方便。可以用 isContinuous()函数来判断图像数组是否为连续的。
问题:如何访问图像中的像素
访问图像中像素的三个方法:
1.指针访问:c操作符[]
2.迭代器iterator
3.动态地址计算
三种方法在访问速度上有差异
第一种:用指针访问 访问速度最快
void colorreduce(Mat& inputImage,Mat& outputImage,int div)
{
outputImage=inputImage.clone();
int rowNumber=outputImage.rows;
int colNumber=outputImage.cols*outputImage.channels();//每一行元素的个数
for(int i=0;i<rowNumber;i++)
{
uchar* data=outputImage.ptr<uchar>(i);
//uchar* data=outputImage.ptr<uchar>(i)[j];//获取第i行第j列元素的值
fo
f497
r(int j=0;j<colNumber;j++)
{
data[j] = data[j] / div*div + div / 2;
}
//*data++ = *data / div*div + div / 2; //所有方法中最快的
}
第二种:用迭代器操作像素
这里,我们只需要获取图像矩阵的begin和end,然后增加迭代直至从begin到end。将*操作符添加到迭代指针前,即可访问当前指向的内容。相比指针容易产生越界的情况,迭代器是绝对安全的
void colorReduce(Mat& inputImage,Mat& outputImage,int div)
{
outputImage = inputImage.clone();
Mat_<Vec3b>::iterator it = outputImage.begin<Vec3b>();
Mat_<Vec3b>::iterator itend = outputImage.end<Vec3b>();
for (; it != itend; ++it)
{
(*it)[0] = (*it)[0] / div*div + div / 2;
(*it)[1] = (*it)[1] / div*div + div / 2;
(*it)[2] = (*it)[2] / div*div + div / 2;
}
第三种:动态地址计算
void colorReduce(Mat& inputImage,Mat& outputImage,int div)
{
outputImage = inputImage.clone();
int rowNumber = outputImage.rows;
int colNumber = outputImage.cols;
for (int i = 0; i < rowNumber; i++)
{
for (int j = 0; j < colNumber; j++)
{
outputImage.at<Vec3b>(i,j)[0]=
outputImage.at<Vec3b>(i,j)[0]/div*div+div/2;
outputImage.at<Vec3b>(i,j)[1]=
outputImage.at<Vec3b>(i,j)[1]/div*div+div/2;
outputImage.at<Vec3b>(i,j)[2]=
outputImage.at<Vec3b>(i,j)[2]/div*div+div/2;
}
}
}
问题:如何显式地创建一个Mat对象
Mat 不但是一个很赞的图像容器类,它同时也是一个通用的矩阵类,所以可以用来创建和操作多维矩阵。创建一个Mat对象有多种方法:
一:Mat() 构造函数
Mat M(2,2, CV_8UC3, Scalar(0,0,255)); cout << "M = " << endl << " " << M << endl << endl;
显示结果:
Scalar 是个short型vector。指定这个能够使用指定的定制化值来初始化矩阵.
二:Create()
M.create(4,4, CV_8UC(2)); cout << "M = "<< endl << " " << M << endl << endl;
结果:
这个创建方法不能为矩阵设初值,它只是在改变尺寸时重新为矩阵数据开辟内存
三:MATLAB形式的初始化方式:
zeros(),
ones(), :eyes() 。使用以下方式指定尺寸和数据类型:
Mat E = Mat::eye(4, 4, CV_64F); cout << "E = " << endl << " " << E << endl << endl; Mat O = Mat::ones(2, 2, CV_32F); cout << "O = " << endl << " " << O << endl << endl; Mat Z = Mat::zeros(3,3, CV_8UC1); cout << "Z = " << endl << " " << Z << endl << endl;
结果:
mat的常见属性
1:data uchar型的指针。Mat类分为了两个部分:矩阵头和指向矩阵数据部分的指针,data就是指向矩阵数据的指针
2:dims 矩阵的维度,例如5*6矩阵是二维矩阵,则dims=2,三维矩阵dims=3.
3:rows 矩阵的行数
4:cols 矩阵的列数
5:size 矩阵的大小,size(cols,rows),如果矩阵的维数大于2,则是size(-1,-1)
6:channels 矩阵元素拥有的通道数
7:type 表示了矩阵中元素的类型以及矩阵的通道个数,它是一系列的预定义的常量,其命名规则为CV_(位数)+(数据类型)+(通道数)。具体的有以下值:
CV_8UC1 | CV_8UC2 | CV_8UC3 | CV_8UC4 |
CV_8SC1 | CV_8SC2 | CV_8SC3 | CV_8SC4 |
CV_16UC1 | CV_16UC2 | CV_16UC3 | CV_16UC4 |
CV_16SC1 | CV_16SC2 | CV_16SC3 | CV_16SC4 |
CV_32SC1 | CV_32SC2 | CV_32SC3 | CV_32SC4 |
CV_32FC1 | CV_32FC2 | CV_32FC3 | CV_32FC4 |
CV_64FC1 | CV_64FC2 | CV_64FC3 | CV_64FC4 |
关于使用data访问图像中像素的一些问题:http://blog.csdn.net/zy122121cs/article/details/47029431
相关文章推荐
- Opencv 中 Mat类的基本操作
- opencv基本操作(五)
- Python OpenCV——基本操作一网打尽
- 【OpenCV 2.4.9 用户指南之一】图像读写、显示、基本操作
- Python下使用OpenCV——图像的基本操作
- OpenCV(四) Opencv中 core 核心模块详解—— Mat类(二)之常见函数及操作
- opencv基本矩阵操作
- OpenCV学习13--基本阈值操作
- python opencv入门 基本图像操作(6)
- OpenCV的基本矩阵操作与示例
- OpenCV 编程简介(矩阵/图像/视频的基本读写操作)
- opencv学习笔记1:矩阵和图像基本操作
- opencv_study第一篇|opencv的安装及基本操作
- OpenCV 编程简介(矩阵/图像/视频的基本读写操作)
- 【Python_OpenCv】笔记4:python,OpenCv中对图片像素的操作以及图片基本属性的获取方法
- OpenCV—基本矩阵操作与示例
- OpenCV学习笔记之(二):图像的基本操作(VS2010+OpenCV3.0)
- Python-OpenCV 处理图像(一):基本操作
- OpenCV-Python learning-5.图像基本操作
- Opencv Mat类的操作符重载及矩阵操作