学习Opencv,图像和大数组类型,Mat类及其相关操作,opencv的入门基础

Mat类相关操作Opencv的入门基础

初始化构造函数

mat类是opencv中一个非常重要的数据结构,在这里先记录一下最基础的知识,也是最重要的知识吧,千里之行始于足下。

构造函数说明
cv:Mat(int rows ,int cows, int type)指定类型的二维数组
CV::Mat(int rows ,int cows,int type,const Saclar&s)指定类型的二维数组,并初始化
CV::Mat(cv::Size sz,int type)指定类型的二维数组,大小由sz定
CV::Mat(int rows ,int cows,int type,void*data,size_t_step=AUTO_STEP)指定类型的二维数组,并指定预先存储的数据
CV::Mat(cv::Size sz,int type,const Saclar&s)指定类型的二维数组,并初始化,大小由sz定
CV::Mat(cv::Size sz,int type,void*data,size_t_step=AUTO_STEP)-指定类型的二维数组,并初始化,大小由sz定,并指定预先存储的数据
cv::Mat(int ndims,const int *sizes,int type)指定类型的多维数组
cv::Mat(int ndims,const int *sizes,int type,const Saclar&s)指定类型的多维数组 ,并初始化
cv::Mat(int ndims,const int sizes,int type,voiddata,size_t_step=AUTO_STEP)指定类型的多维数组,并指定预先存储的数据

数据类型
CV_8U-8 位无符号整数 (0……255)
• CV_8S-8 位符号整数 (-128……127)
• CV_16U-16 位无符号整数 (0……65535)
• CV_16S-16 位符号整数 (-32768……32767)
• CV_32S-32 位符号整数 (-2147483648……2147483647)
• CV_32F-32 位浮点数 (-FLT_MAX ………FLT_MAX,INF,NAN)
• CV_64F-64 位浮点数(-DBL_MAX ……….DBL_MAX,INF,NAN)
#define CV_8U 0 //对应uchar
#define CV_8S 1 //对应char
#define CV_16U 2 //对应ushort
#define CV_16S 3 //对应short
#define CV_32S 4 //对应int
#define CV_32F 5 //对应float
#define CV_64F 6 //对应double
代码演示

#pragma once
#include <iostream>
#include <string>
#include<cctype>
#include <fstream>
#include<vector>
#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/highgui/highgui.hpp"
using namespace cv;
using namespace std;
int main()
{
	//cv:Mat(int rows ,int cows, int type) 
	Mat m = Mat(10, 10, CV_16F);
	cout << m << endl;//10*10的矩阵未初始化
	//CV::Mat(int rows ,int cows,int type,const Saclar&s)
	Mat m2 = Mat(10, 10, CV_16F, Scalar(0));//初始化均为0
	int a[3][2] = { {5,3},{4,5},{5,6} };
	//CV::Mat(int rows ,int cows,int type,void*data,size_t_step=AUTO_STEP)
	Mat m3 = Mat(3, 2, CV_32S,a);//指定数组初始化
	//CV::Mat(cv::Size sz,int type,const Saclar&s)
	Mat m4 = Mat(Size(10,10), CV_16F, Scalar(0));//初始化均为0
	//CV::Mat(cv::Size sz,int type,void*data,size_t_step=AUTO_STEP)
	Mat m5 = Mat(Size(2,3), CV_32S, a);//指定数组初始化,注意和m3的方式略有不同
	cout << m3 << endl;
	cout << m2 << endl;
	cout << m5 << endl;
	cout << "hello,world" << endl;
	system("pause");
}

复制数据的构造函数

cv::Mat(const Mat&mat); 复制构造函数
CV::Mat(const Mat&mat,const cv::Range&rows,CV::Rang&clos) 从指定行列中复制构造
CV::Mat((const Mat&mat,const cv::Rect&roi) 从感兴趣区域复制
CV::Mat(const Mat&mat,const Range *ranges) 从泛化的感兴趣区域复制
cv::Mat(const cv::MatExpr&expr) 从其他矩阵的线性代数表达式中生成新的复制构造函数
代码演示

#pragma once
#include <iostream>
#include <string>
#include<cctype>
#include <fstream>
#include<vector>
#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/highgui/highgui.hpp"
using namespace cv;
using namespace std;
int main()
{
	Mat m = imread("D:\\My code\\Python\\opencv\\study\\01.jpg");
	//cv::Mat(const Mat&mat); 
	Mat b = Mat(m);
	//CV::Mat(const Mat&mat, const cv::Range&rows, CV::Rang&clos)
	Mat r = Mat(m, Range(200, 300), Range(100, 200));//选取区域rows::Range(200, 300),cols:: Range(100, 200)
	//CV::Mat((const Mat&mat,const cv::Rect&roi) 
	Mat rb = Mat(m, Rect(100, 200, 100, 100));//和r的结果一样
	cout << "hello,world" << endl;
	system("pause");
}

结果
在这里插入图片描述

模板构造

(Mat_<>()<<2,345,53,) ,自定义输入矩阵。

Mat tt = (Mat_<int>(2, 3) << 3, 4, 5, 6, 7, 8);

访问Mat数组的方法

1.at<>方法相对来说简单

Mat tt = (Mat_<int>(2, 3) << 3, 4, 5, 6, 7, 8);
tt.at<int>(1,1);//结果为7
tt.at<int>(3)//结果为6 m.at<>(i)  访问数组中的第i个元素


2使用Mat的成员函数ptr<>()

Mat tt = (Mat_<int>(2, 3) << 3, 4, 5, 6, 7, 8);
int *p=tt.ptr<int>(1);//返回的是一个指针
	
cout <<p[1] << endl;通过指针的方式访问,也可以*(p+1)结果为7

3.内置的迭代器(推荐使用迭代器或者指针的方式访问元素)
此处的迭代器和c++中的迭代器用法类似,这种方法能够较为高效的访问数组元素,而且不容易发生数组的的越界行为

	Mat tt = (Mat_<int>(2, 3) << 3, 4, 5, 6, 7, 8);
	cout << tt << endl;

	MatIterator_<int>it = tt.begin<int>();
	while (it!=tt.end<int>())
	{
		cout << *it << endl;
		it++;
	}

通过块访问数组元素

示例描述
m.row(i)m中的第i行数组
m.col(j)m中的第j列数组
m.rowRang(i0,i1)m中第i行到i1行的数组
m.colRang(j0,j1)m中第j列到j1列的数组
m.rowRang(Rang(i0,i1))m中第i行到第i1行的数组
m.colRang(Rang(j0,j1))m中第j列到j1列的数组
m.diag(d)m中偏移为d的对角线所组成的数组
m(Rang(i0,j0),Rang(j0,j1))m中第j列到j1列到第i行到第i1行构成的新数组
m(Rect())和上一个类似

示例代码:

Mat tt = (Mat_<int>(3, 3) << 3, 4, 5, 6, 7, 8,9,10,11);
	cout << tt << endl;//[3, 4, 5; 6, 7, 8;9, 10, 11]
	cout << tt.row(1) << endl;//[6, 7, 8]
	cout << tt.col(1) << endl;//[4;7; 10]
	cout << tt.colRange(0, 2) << endl;//[3, 4;6, 7;9, 10]
	cout << tt.rowRange(0, 2) << endl;//[3, 4, 5; 6, 7, 8]
	cout << tt.diag(1) << endl;//[4; 8]

被重载的运算操作符+,-,*

示例描述
m0+m1,m0-m1矩阵的加减
m0+s0,m0-s0矩阵和单个元素的加减
s*m0矩阵和单个元素的乘法
m0.mul(m1),m0/m1矩阵元素的逐一乘除
m0.inv()矩阵的逆
m0.t()矩阵的转置
m0>m1矩阵的比较,逐个元素
m0^m1 ,m0&m1矩阵的逐个元素的逻辑操作
min(m0,m1),max(m0,m1),min(m0,s)矩阵和矩阵之间单个元素取最小最大,矩阵和数之间的比较
abs(m0)矩阵的逐个元素求绝对值

代码示例

	Mat tt = (Mat_<double>(3, 3) << 1, 4, 5, 6, 7, 8,9,10,11);
	Mat tt3 = (Mat_<double>(2, 2) << 1, 4, 5, 6);
	Mat tt2 = (Mat_<double>(3, 3) << 5, 6, 5, 6, 7, 8, 9, 10,12);

	cout << "(tt+tt2):"<<endl<<(tt+tt2) << endl;
	cout << "(tt+2):" << endl<<(tt+2) << endl;
	cout << "(tt*2):" << endl<<(tt*2) << endl;
	cout << "(tt.mul(tt2)):" << endl << (tt.mul(tt2)) << endl;
	cout << "(tt/tt2):" << endl << (tt/tt2) << endl;
	cout << "tt3.inv():" << endl << (tt3.inv() )<< endl;
	cout << "tt.t():" << endl << tt.t() << endl;
//结果
#if 0
(tt+tt2):
[6, 10, 10;
 12, 14, 16;
 18, 20, 23]
(tt+2):
[3, 6, 7;
 8, 9, 10;
 11, 12, 13]
(tt*2):
[2, 8, 10;
 12, 14, 16;
 18, 20, 22]
(tt.mul(tt2)):
[5, 24, 25;
 36, 49, 64;
 81, 100, 132]
(tt/tt2):
[0.2, 0.6666666666666666, 1;
 1, 1, 1;
 1, 1, 0.9166666666666666]
tt3.inv():
[-0.4285714285714285, 0.2857142857142857;
 0.3571428571428571, -0.07142857142857142]
tt.t():
[1, 6, 9;
 4, 7, 10;
 5, 8, 11]
 #end if

向量的叉乘和点乘

m.cross(m1) 叉乘, m0.dot(m1)点乘

Mat tt1 = (Mat_<double>(1, 3) << 1, 4, 5);
Mat tt2 = (Mat_<double>(3, 1) << 1, 3, 5);
cout << (tt1.dot(tt2.t())) << endl;//38
cout << (tt1.cross(tt2.t())) << endl;//[5, 0, -1]
//这里不需要将两个向量写成3*1,1*3的形式,都是3*1和3*1就好了。

数组其他的成员函数

示例描述
m1.clone()克隆一个矩阵,重新分配存储空间
m1.copyTo(m2)把m1复制给m2
m1.converTo(m2,type)重新调整Mat的数据类型
m1.reshap(chan,rows)重新调整数组的形状和reshape一样
m1.push_back(m)在末尾添加一行
m1.total()计算数组序列的元素的数目
m1.elemSize()返回m0的位长度
m1.type()返回元素类型
m1.depth()返回通道中的元素类型
m1.channels()返回通道数目
m1.empty()检查矩阵是否为空

这些方法比较简单,在此就不作代码演示,如有需要可以百度具体的函数用法。

矩阵的操作(基础操作)

cv::abs() 计算矩阵的绝对值

Mat tt1 = (Mat_<double>(1, 3) << -1, 2, 5);
	Mat tt2 = (Mat_<double>(1, 3) << 1, 3, 5);
	cout << abs(tt1) << endl;//[1, 2, 5]
	cout << abs(tt1-tt2) << endl;//[2, 1, 0]

cv::add(src,src1,dst)矩阵相加

Mat tt1 = (Mat_<double>(1, 3) << -1, 2, 5);
	Mat tt2 = (Mat_<double>(1, 3) << 1, 3, 5);
	Mat dst;
	add(tt1, tt2, dst);
	cout << dst << endl;//[0, 5, 10]

cv::addweighted(src1,alpha,src2,beta,gamma,srt)带有权重的相加
dst=src1alpha+src2beta+gamma

Mat tt1 = (Mat_<double>(1, 3) << -1, 2, 5);
	Mat tt2 = (Mat_<double>(1, 3) << 1, 3, 5);
	Mat dst;
	addWeighted(tt1,0.5, tt2,0.5,1, dst);
	cout << dst << endl;//[1, 3.5, 6]

应用:图像混合

Mat m = imread("D:\\My code\\Python\\opencv\\study\\01.jpg");
	Mat b = imread("D:\\My code\\Python\\opencv\\study\\04.jpg");
	Mat b1 (b, Rect(100, 100, 200, 100));//选取的roi区域,浅拷贝
	Mat m1 (m, Rect(200, 140, 200, 100));//选取的roi区域,浅拷贝
	addWeighted(b1, 0.5, m1, 0.5, 0, m1);//把相加后的结果放到m中的m1区域
	imshow("dd", m);

cv::bitwise_and(),cv::bitwise_not(),cv::bitwise_or(),cv::bitwise_xor() 按位操作
cv::determinant(m0),计算方阵的行列式
cv::eigen(m0);计算方阵的特征值和特征向量

	Mat tt=(Mat_<double>(3, 3) << 12, 3, 21, 3, 12, 31, 2, 4, 3);
	Mat det = (Mat_<double>(1, 3) << 0, 0, 0);//注意类型为CV_64f或者cv_32f
	eigen(tt, det);
	cout << det << endl;//[46.8162253176873;9.208629402538843 -29.02485472022613]

cv::exp()元素逐个求幂

函数描述
cv::Mahalanobis()计算两个矩阵的马氏距离
cv::mean计算矩阵元素的平均值
CV::merge将多个单通道合成一个多通道
cv::norm计算两个矩阵的归一化相关系数
cv::normlize归一化处理
cv::minMaxLoc(src,&min,&max,&Point1,&point2)计算矩阵的最大最小值
cv::randu用均匀分布填充矩阵
cv::randn用正态分布填充矩阵
cv::randShuffle打乱矩阵
cv::setIdentity()将矩阵的对角线设置成1,其他设置成0
cv:solve()求解线性方程的解
cv:sort()排序矩阵中任意行或者列的元素
cv:theRNG()返回随机数生成器

cv::norm(src1)
cv::norm(src1,src2)

在这里插入图片描述不同参数的计算方法
void cv::normalize ( InputArray src,
InputOutputArray dst,
double alpha = 1,
double beta = 0,
int norm_type = NORM_L2,
int dtype = -1,
InputArray mask = noArray()
)

vector<double> positiveData = { 2.0, 8.0, 10.0 };
vector<double> normalizedData_l1, normalizedData_l2, normalizedData_inf, normalizedData_minmax;
// Norm to probability (total count)
// sum(numbers) = 20.0
// 2.0      0.1     (2.0/20.0)
// 8.0      0.4     (8.0/20.0)
// 10.0     0.5     (10.0/20.0)
normalize(positiveData, normalizedData_l1, 1.0, 0.0, NORM_L1);
// Norm to unit vector: ||positiveData|| = 1.0
// 2.0      0.15
// 8.0      0.62
// 10.0     0.77
normalize(positiveData, normalizedData_l2, 1.0, 0.0, NORM_L2);
// Norm to max element
// 2.0      0.2     (2.0/10.0)
// 8.0      0.8     (8.0/10.0)
// 10.0     1.0     (10.0/10.0)
normalize(positiveData, normalizedData_inf, 1.0, 0.0, NORM_INF);
// Norm to range [0.0;1.0]
// 2.0      0.0     (shift to left border)
// 8.0      0.75    (6.0/8.0)
// 10.0     1.0     (shift to right border)
normalize(positiveData, normalizedData_minmax, 1.0, 0.0, NORM_MINMAX);

void cv::normalize ( const SparseMat & src,
SparseMat & dst,
double alpha,
int normType
)
src 输入矩阵
dst 输出矩阵
alpha 归一化的最低边界.
normType 归一化方法
在这里插入图片描述

小结

1.本文介绍了Mat类的一些常用的用法,具体的操作,大家还能访问官方网站https://docs.opencv.org/master/d2/de8/group__core__array.html#gad12cefbcb5291cf958a85b4b67b6149f
2.对矩阵的操作是最基本的操作,希望该篇文章对大家有所帮助

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值