图像处理过程中,对图像矩阵的每一个元素进行操作是十分重要的。

本博文对OpenCV中的Mat矩阵的操作做了一次总结,方便我自己查阅。

Mat 基础

在计算机中,图像在本质上是一个数组。Mat就是图像在OpenCV中的表现形式。

基本属性

cols:矩阵列数
rows:矩阵行数
channels:通道数
type:数据类型
total:矩阵总元素数
data:指向矩阵数据块的指针

opencv矩阵映射 opencv矩阵操作_浮点型


opencv矩阵映射 opencv矩阵操作_OpenCV_02

type

图像像素的类型。

opencv矩阵映射 opencv矩阵操作_浮点型_03

cols rows channels total data

opencv矩阵映射 opencv矩阵操作_最小值_04

opencv矩阵映射 opencv矩阵操作_opencv矩阵映射_05


指针未显示,但已占位置。

Mat的创建

建立矩阵必须指定其存储的数据类型,常见的几种如下:

CV_8UC1// 8位无符号单通道
CV_8UC3// 8位无符号3通道
CV_8UC4
CV_32FC1// 32位浮点型单通道
CV_32FC3// 32位浮点型3通道
CV_32FC4

创建方法:

cv::Mat a(cv::Size(5,5),CV_8UC1);//单通道
cv::Mat b = cv::Mat(cv::Size(5,5),CV_8UC3); //3通道

初始化方法:与matlab类似,都有相应的函数

cv::Mat z = cv::Mat::zeros(cv::Size(5,5),CV_8UC1); // 全零矩阵
	cv::Mat o = cv::Mat::ones(cv::Size(5,5),CV_8UC1);  // 全1矩阵
	cv::Mat e = cv::Mat::eye(cv::Size(5,5),CV_32FC1);  // 对角线为1的对角矩阵

遍历Mat元素

at(i,j)

Mat类为我们提供了at方法,它是一个模板函数,可以获取到任何类型的图像上的点。

image.at<uchar>(i,j)//取出灰度图像第i行j列的点
image.at<Vec3b>(i,j)[k]//取出彩色图像中i行j列第k通道的点

用这种方法比较慢

指针遍历图像

for(int i = 0; i < image.rows; i++){
	uchar* inData = image.ptr<uchar>(i);//获取第i行的指针
	for(int j = 0; i < image.cols; j++){
		cout<<*inData++;
	}
}

opencv矩阵映射 opencv矩阵操作_opencv_06


比较高效的方法

特殊情况

OpenCV存储行时有可能是不连续的,所以读取时只能一行一行读。不过OpenCV提供了在isContinuous()来判断image存储是否是连续,连续为true,不连续为false。如果连续,就可以将数据看成一行了。

opencv矩阵映射 opencv矩阵操作_浮点型_07


如果不是就按上面的来,这是最高效的做法。

迭代器遍历

opencv矩阵映射 opencv矩阵操作_opencv矩阵映射_08


这种方法的优点是足够安全。

矩阵运算

矩阵加减法

cv::Mat a= Mat::eye(Size(3,2), CV_32F);
cv::Mat b= Mat::ones(Size(3,2), CV_32F);
cv::Mat c= a+b;
cv::Mat d= a-b;

矩阵乘除法

Mat m1= Mat::eye(2,3, CV_32F); 
Mat m2= Mat::ones(3,2, CV_32F);
// Scalar by matrix
cout << "\nm1.*2 = \n" << m1*2 << endl;
	// matrix per element multiplication
cout << "\n(m1+2).*(m1+3) = \n" << (m1+1).mul(m1+3) << endl;
// Matrix multiplication
cout << "\nm1*m2 = \n" << m1*m2 << endl;

opencv矩阵映射 opencv矩阵操作_opencv矩阵映射_09

矩阵转置

Mat m1= Mat::eye(2,3, CV_32F);	
Mat m1t = m1.t();

矩阵的逆

Mat meinv = me.inv();

矩阵的非零元素个数

int nonZerosNum = countNonZero(me);

均值和标准差

Mat mean;
	Mat stddev;
	meanStdDev(me, mean, stddev); //me为前文定义的5×5对角阵
	cout<<"mean = "<<mean<<endl;
	cout<<"stddev = "<<stddev<<endl;

最大最小值

void minMaxLoc(InputArray src, CV_OUT double* minVal,
                           CV_OUT double* maxVal=0, CV_OUT Point* minLoc=0,
                           CV_OUT Point* maxLoc=0, InputArray mask=noArray());

参数:

  • src – 输入单通道矩阵(图像)
  • minVal – 指向最小值的指针, 如果未指定则使用NULL
  • maxVal –指向最大值的指针,如果未指定则使用NULL
  • minLoc – 指向最小值位置(2维情况)的指针, 如果未指定则使用NULL
  • maxLoc – 指向最大值位置(2维情况)的指针, 如果未指则使用NULL
  • mask – 可选的蒙版,用于选择待处理子区域