[OpenCV][C++编程] cv::mat的定义与赋值
文章目录
0.在pro文件中添加opencv的库
0.1 INCLUDEPATH
可以通过在/目录下直接搜索opencv,确定opencv所在的目录:
INCLUDEPATH += \
/usr/include/opencv4
0.2 LIBS
LIBS += \
-lopencv_core -lopencv_highgui -lopencv_imgproc -lopencv_ml
- lopencv_core 是opencv的核心,
- -lopencv_highgui包含读取图像和显示图像的函数
- -lopencv_imgproc包含图像处理函数(非机器学习方法),例如线性滤波,边缘检测、膨胀腐蚀、检测直线、仿射变换等等。
- -lopencv_ml包含机器学习算法(贝叶斯分类、k-近邻分类器、SVM、决策树、EM算法等待)
1. cv::Mat的创建
1.1 默认的构造函数
可以直接采用下面的形式:cv::Mat mat(sizeRow,sizeCol,type)
定义mat变量的尺寸和类型。
type可选项有CV_8UC1、CV_8SC1等等。它的数据含义是:
CV_数据类型_数据的通道数量
- 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代表数据通道数:
- C1:灰度图像,单个数字
- C2:每一个可以表示一个二维向量
- C3:RGB图像
- C4:PNG格式图像除了RGB,还有一个透明度通道。
#include <QCoreApplication>
#include<opencv/cv.h>
#include<QDebug>
#include<iostream>
int main(int argc, char *argv[])
{
//QCoreApplication a(argc, argv);
// cv::Mat mat1 = cv::Mat_<float>(3,3);
// std::cout<<"mat1 size is " << mat1.size<<std::endl;
// std::cout<<"mat1 type is " << mat1.type()<<std::endl;
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
1.2使用mat_<变量类型>(变量尺寸)函数进行创建(推荐使用)
cv::Mat_<类型>(sizeRow,sizeCol)
例如下面的代码是创建了一个3*3
的Mat变量,变量的类型都是float
#include <QCoreApplication>
#include<opencv/cv.h>
#include<QDebug>
#include<iostream>
int main(int argc, char *argv[])
{
//QCoreApplication a(argc, argv);
cv::Mat mat1 = cv::Mat_<float>(3,3);
//std::cout<< "mat1:"<mat1<<std::endl ;
std::cout<<"mat1 size is " << mat1.size<<std::endl;
return 0;
}
输出的结果为:
mat1 size is 3 x 3
mat1 type is 5
1.3 构造一些特殊矩阵
生成零矩阵、全1矩阵、单位矩阵、对角矩阵。
- cv::Mat::zeros()
- cv::Mat::ones()
- cv::Mat::eye()
- cv::Mat::diag();
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]
1.4 克隆其他矩阵
同尺寸克隆,直接通过 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不变。
1.5 基于其他mat变量建立更小尺寸的mat
//基于某个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]
2.mat的赋值
2.1 针对某个点的赋值
通过 mat.at<变量类型>(numRow,numCol) = num;
命令对mat变量中某个索引值进行赋值。例如在1.5中出现的赋值。
2.2在创建mat变量时赋值
在采用构造方式创建变量时,直接附在最后一个变量。
给矩阵中每个像素赋值的参数变量,例如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
2.3 采用枚举法赋值
这种赋值方式是将矩阵中所有的元素都一一枚举出,并用数据流的形式赋值给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);
2.4 循环赋值
与通过枚举法赋值方法相类似,循环法赋值也是对矩阵中的每一位元素进行赋值,但是可以不在声明变量的时候进行赋值,而且可以对矩阵中的任意部分进行赋值:
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;
}
}
更多推荐
所有评论(0)