Mat 矩阵创建
方法1. 使用Mat()构造函数
cv::Mat M1(2,2,CV_8UC3,Scalar(0,0,255))
这个函数的意思是,创建了一个名为M1的Mat,该Mat的尺寸为2,2,类型
为CV_8UC3,即8位uchar类型,该Mat通道数为3。这个mat的每一个元素
包含了3个通道或者说3个数值。然后用0,0,255为每一个元素赋值。
这里8位uchar型的取值为0~255,实际上如果一个Mat是用来表示RGB图像
的时候应该声明为CV_8UC3型
Mat型可以定义各种类型,可按F12快捷键查看头文件中的定义。定义的方式如下:CV_(位数)+(数据类型)+(通道数)
如CV_32FC1表示32位float型数据,有如下类型
- 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
方法2:使用create()函数,代码如下
cv::Mat M3;
M3.create(3,4,CV_8UC3);
表示首先声明一个mat型,名叫M3,其尺寸为3行,4列。
方法3: 使用内置函数初始化
- 全初始化为0
Mat initZero=Mat::zeros(2,2,CV_32F);
- 全初始化为1
Mat initOne= Mat::ones(2,2,CV_32F);
- 全初始化为对角阵
Mat initEye=Mat::eye(2,2,CV_32F);
Mat 矩阵复制
1. 浅复制
cv::Mat srcM(2,2,CV_8UC3,Scalar(0,0,255))
cv::Mat dstM;
dstM=srcM;
表示首先声明一个mat名为 srcM,并初始化。然后声明一个mat名为dstM通过“=”把srcM复制给dstM。这样生成的矩阵,只是新生成一个矩阵头,dstM的data依然指向矩阵srcM的data,类似C++中的浅拷贝。
:
2. 深复制
cv::Mat srcM(2,2,CV_8UC3,Scalar(0,0,255))
cv::Mat dstM;
srcM.copyTo(dstM);
通过copyTo函数,可以实现深复制。也就是dstM是一个全新的矩阵,他在内存中的地址和srcM是不一样的。另外copyTo函数还可以加上掩模参数
Mat 矩阵复制遍历
当我们想读取或者修改Mat的任意内容时候,可以用以下方式访问Mat。
1. 利用指针.ptr
int height= image.rows; //行数
Int width = image.cols * image.channels(); //每行元素的总元素数量
for (int j=0; j<height; j++)
{
//定义指针data,其值为image的第j行的头地址
uchar* data= image.ptr<uchar>(j);
for (int i=0; i<width; i++)
{
//----开始处理每个像素,每个元素的值减少到1/2-----
data[i]= data[i]/2;
//-------------结束像素处理------------------------
} //单行处理结束
}
2.利用.at
遍历3通道的RGB图像
int height= image.rows; //行数
Int width = image.cols ; //每行元素的总元素数量
for (int j=0; j<height; j++)
{
for (int i=0; i<width; i++)
{
//----开始处理每个像素,每个元素的值减少到1/2-----
image.at<Vec3b>(j,i)[0]= image.at<Vec3b>(j,i)[0]/div*div + div/2;
image.at<Vec3b>(j,i)[1]= image.at<Vec3b>(j,i)[1]/div*div + div/2;
image.at<Vec3b>(j,i)[2]= image.at<Vec3b>(j,i)[2]/div*div + div/2;
//-------------结束像素处理------------------------
} //单行处理结束
}
遍历单通道的灰度图
int height= image.rows; //行数
Int width = image.cols * image.channels(); //每行元素的总元素数量
for (int j=0; j<height; j++)
{
for (int i=0; i<width; i++)
{
//----开始处理每个像素,每个元素的值减少到1/2-----
image.at<uchar>(j,i)= image.at<uchar>(j,i)/2;
//-------------结束像素处理------------------------
} //单行处理结束
}
3.利用迭代器
Mat M = Mat(100, 150, CV_8UC3);
cout << "rows=" << M.rows << ",cols=" << M.cols << endl;
Mat_<Vec3b>::iterator it = M.begin<Vec3b>();//初始位置的迭代器
Mat_<Vec3b>::iterator itend = M.end<Vec3b>();//终止位置的迭代器
for (; it != itend; it++)
{
//处理BGR三个通道
(*it)[0] = 182;//B
(*it)[1] = 194;//G
(*it)[2] = 154;//R
}
Mat 数学运算
Mat 加减乘除
相同类型的Mat 矩阵可以直接使用运算符进行加减乘除,其中代码矩阵对应位置的元素进行加减乘除
#include <opencv2/opencv.hpp>
#include <iostream>
#include <vector>
using namespace std;
using namespace cv;
int main() {
Mat a=(Mat_<float>(2,2)<<1,1,1,1);
Mat b=(Mat_<float>(2,2)<<1,2,3,4);
Mat show;
//1.add
//show=r.rows(0);
show=a+b;
cout<<show<<endl;
//2.subtract
show=a-b;
cout<<show<<endl;
//3., multiply
show=a*b;
cout<<show<<endl;
//4.divide
show=a/b;
cout<<show<<endl;
return 0;
}
结果如下:
[2, 3;
4, 5]
[0, -1;
-2, -3]
[4, 6;
4, 6]
[1, 0.5;
0.33333334, 0.25]
Mat 位运算
mat的位运算包含与或非、异或操作等。
- 按位与:bitwise_and
- 按位或:bitwise_or
- 按位异或:bitwise_xor
- 按位非:bitwise_not
Mat 矩阵求逆和求转置
- 用inv()求逆
- 用t()求转置
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
int main() {
Mat r=(Mat_<float>(2,2)<<1,1,0,2);
cout<<r<<endl;
cout<<r.inv()<<endl;
cout<<r.t()<<endl;
return 0;
}