可以通过在/目录下直接搜索opencv,确定opencv所在的目录:
INCLUDEPATH += \
/usr/include/opencv4
LIBS += \
-lopencv_core -lopencv_highgui -lopencv_imgproc -lopencv_ml
可以直接采用下面的形式:cv::Mat mat(sizeRow,sizeCol,type)
定义mat变量的尺寸和类型。
type可选项有CV_8UC1、CV_8SC1等等。它的数据含义是:
CV_数据类型_数据的通道数量
#define CV_8U 0
#define CV_8S 1
#define CV_16U 2
#define CV_16S 3
#define CV_32S 4
#define CV_32F 5
#define CV_64F 6
#define CV_16F 7
通过mat.type()可以输出mat变量的类型。
C1,C2,C3,C4代表数据通道数:
#include
#include
#include
#include
int main(int argc, char *argv[])
{
//QCoreApplication a(argc, argv);
// cv::Mat mat1 = cv::Mat_(3,3);
// std::cout<<"mat1 size is " << mat1.size<
// std::cout<<"mat1 type is " << mat1.type()<
cv::Mat mat2(4,4,CV_8UC1);
std::cout<<"mat2 size is " << mat2.size<<std::endl;
std::cout<<"mat2 type is " << mat2.type()<<std::endl;
return 0;
}
输出结果为:
mat2 size is 4 x 4
mat2 type is 0
cv::Mat_<类型>(sizeRow,sizeCol)
例如下面的代码是创建了一个3*3
的Mat变量,变量的类型都是float
#include
#include
#include
#include
int main(int argc, char *argv[])
{
//QCoreApplication a(argc, argv);
cv::Mat mat1 = cv::Mat_<float>(3,3);
//std::cout<< "mat1:"
std::cout<<"mat1 size is " << mat1.size<<std::endl;
return 0;
}
输出的结果为:
mat1 size is 3 x 3
mat1 type is 5
生成零矩阵、全1矩阵、单位矩阵、对角矩阵。
cv::Mat mat2;
mat2= cv::Mat::zeros(3,3,CV_16U);
std::cout<<mat2<<std::endl;
mat2= cv::Mat::ones(3,3,CV_16U);
std::cout<<mat2<<std::endl;
mat2= cv::Mat::eye(3,3,CV_16U);
std::cout<<mat2<<std::endl;
结果:
[0, 0, 0;
0, 0, 0;
0, 0, 0]
[1, 1, 1;
1, 1, 1;
1, 1, 1]
[1, 0, 0;
0, 1, 0;
0, 0, 1]
同尺寸克隆,直接通过 mat.clone( )
指令就可以了。被克隆的
//从其他矩阵克隆
cv::Mat mat2;
mat2= cv::Mat::eye(3,3,CV_16U);
cv::Mat mat3 = mat2.clone();
std::cout<<mat3<<std::endl;
输出结果:
[1, 0, 0;
0, 1, 0;
0, 0, 1]
缩小尺寸克隆,需要
需要注意的是,直接赋值并不定于克隆:例如mat3 = mat2
只是把mat2的头部指针赋值为mat3,修改mat2或者mat3中任意一个,其他一个都会跟着修改。而mat3= mat2.clone()则创建了完全独立的变量mat3。例如下面的代码,运行结果不一样。
[std::cout<<mat2<<std::endl;](<//从其他矩阵克隆 对比 直接赋值
cv::Mat mat2;
mat2= cv::Mat::eye(3,3,CV_16U);
cv::Mat mat3 = mat2.clone();
cv::Mat mat4 = mat2;
std::cout%3C<"mat2:"<<std::endl<<mat2<<std::endl;
mat4.at<uint16_t%3E(0,0) = 0;
std::cout<<"mat2:"<<std::endl<<mat2<<std::endl;
std::cout<<"mat3:"<<std::endl<<mat3<<std::endl;>)
结果:
mat2:
[1, 0, 0;
0, 1, 0;
0, 0, 1]
mat2:
[0, 0, 0;
0, 1, 0;
0, 0, 1]
mat3:
[1, 0, 0;
0, 1, 0;
0, 0, 1]
mat4和mat2是指向同一个地址,而mat3是单独地址。所以改变mat4的值后,mat2也改变了,而mat3不变。
//基于某个mat变量,建立更小尺寸的mat,发现是共用指针的。
cv::Mat mat2;
mat2= cv::Mat::eye(5,5,CV_16U);
std::cout<<"mat2:"<<std::endl<<mat2<<std::endl;
cv::Mat mat3(mat2,cv::Range(0,3),cv::Range(0,3));
std::cout<<"mat3:"<<std::endl<<mat3<<std::endl;
std::cout<<"将mat3 的 (0,0)元素赋值为0"<<std::endl;
mat3.at<uint16_t>(0,0) = 0;
std::cout<<"mat2:"<<std::endl<<mat2<<std::endl;
结果:
mat2:
[1, 0, 0, 0, 0;
0, 1, 0, 0, 0;
0, 0, 1, 0, 0;
0, 0, 0, 1, 0;
0, 0, 0, 0, 1]
mat3:
[1, 0, 0;
0, 1, 0;
0, 0, 1]
将mat3 的 (0,0)元素赋值为0
mat2:
[0, 0, 0, 0, 0;
0, 1, 0, 0, 0;
0, 0, 1, 0, 0;
0, 0, 0, 1, 0;
0, 0, 0, 0, 1]
通过 mat.at<变量类型>(numRow,numCol) = num;
命令对mat变量中某个索引值进行赋值。例如在1.5中出现的赋值。
在采用构造方式创建变量时,直接附在最后一个变量。
给矩阵中每个像素赋值的参数变量,例如Scalar(0, 0, 255)。_
cv::Mat a(2, 2, CV_8UC3, cv::Scalar(0,0,255));//创建一个3通道矩阵,每个像素都是0,0,255
cv::Mat a(2, 2, CV_8UC3, cv::Scalar(0,255));//创建一个2通道矩阵,每个像素都是0,255
cv::Mat a(2, 2, CV_8UC1, cv::Scalar(255));//创建一个单通道矩阵,每个像素都是255
这种赋值方式是将矩阵中所有的元素都一一枚举出,并用数据流的形式赋值给Mat类。具体赋值形式:
cv::Mat a = (cv::Mat_<int>(3, 3) << 1, 2, 3, 4, 5, 6, 7, 8, 9);
也可以把需要赋值的数写成列表
float a[8] = { 5,6,7,8,1,2,3,4 };
cv::Mat b = cv::Mat(2, 2, CV_32FC2, a);
与通过枚举法赋值方法相类似,循环法赋值也是对矩阵中的每一位元素进行赋值,但是可以不在声明变量的时候进行赋值,而且可以对矩阵中的任意部分进行赋值:
cv::Mat c = cv::Mat_<int>(3, 3); //定义一个3*3的矩阵
for (int i = 0; i < c.rows; i++) //矩阵行数循环
{
for (int j = 0; j < c.cols; j++) //矩阵列数循环
{
c.at<int>(i, j) = i+j;
}
}