当前位置: 代码迷 >> 综合 >> OpenCV4 中图像容器Mat以及矩阵的一些运算
  详细解决方案

OpenCV4 中图像容器Mat以及矩阵的一些运算

热度:31   发布时间:2023-12-10 02:14:01.0

作者:RayChiu_Labloy
版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处


目录

图像和矩阵:

OpenCV中的图像容器Mat

先创建一个图像容器Mat感受一下:

谈一下第三个参数CV_8UC1图像文件格式:

遍历Mat矩阵元素(图像像素值):

使用Mat进行各种矩阵元素级运算:

C++实现矩阵的创建和运算:

zeros()函数创建Mat和任意颜色创建Mat


图像和矩阵:

现实中我们看到的图像是这样的(找了一个模糊的单通道灰度图像):

计算机读取的其实是这样: 

        所以在计算机视觉领域处理图像实际操作的是数字,是一个一个的像素,图像整体在计算机看来就是一个个数值矩阵,那么为了承载图像需要一些矩阵容器、图像容器。

OpenCV中的图像容器Mat

        C++操作矩阵的库有很多,机器视觉方向最火的当属OpenCV,其图像容器Mat提供了非常方便的矩阵操作来处理数字化图像。Mat不但是一个非常有用的图像容器类,同时也是一个通用的矩阵类 2--创建一个Mat对象的方法很多。

先创建一个图像容器Mat感受一下:

//声明并初始化
int row = 3;
int col = 4;
cv::Mat a(row, col, CV_8UC1, cv::Scalar(0));//声明后初始化
cv::Mat a2;
a2.create(5,4,CV_32FC3);  //生成5行4列,float类型3通道矩阵,这个方法不能赋值
a2.setTo(cv::Scalar(0.0,1.0,2.0)); //可以配合这个函数来使用

OpenCV关于矩阵的操作大多数都允许带掩模进行。譬如

cv::Mat a;
a.create(5,4,CV_8UC1);
a.setTo(1, mask);

        其中mask是一个和a同size的矩阵,mask中非零的位置,a的对应位置的元素会被set为1,其他部分不变。mask默认值是全非零,也就是说默认对a的所有元素都执行操作。

谈一下第三个参数CV_8UC1图像文件格式:

写法格式定义:CV_<bit_depth>(S|U|F)C<number_of_channels>

具体:

     1--bit_depth---比特数---代表8bite,16bites,32bites,64bites---举个例子吧--比如说,如如果你现在创建了一个存储--灰度图片的Mat对象,这个图像的大小为宽100,高100,那么,现在这张灰度图片中有10000个像素点,它每一个像素点在内存空间所占的空间大小是8bite,8位--所以它对应的就是CV_82--S|U|F--S--代表---signed int---有符号整形U--代表--unsigned int--无符号整形F--代表--float---------单精度浮点型3--C<number_of_channels>----代表---一张图片的通道数,比如:1--灰度图片--grayImg---是--单通道图像2--RGB彩色图像---------是--3通道图像3--带Alph通道的RGB图像--是--4通道图像

        常用的一些对应关系:CV_8U --- uchar, CV_16U --- ushort, CV_32F --- float, CV_64F --- double 

遍历Mat矩阵元素(图像像素值):

单通道:

cv::Mat a(5, 4, CV_8UC1, cv::Scalar(0));for (int r = 0; r < a.rows; r++)
{for (int c = 0; c < a.cols; c++){std::cout<<(int)a.ptr<uchar>(r)[c]<<std::endl;}
}

如果是3通道,例如CV_32FC3,就在a.ptr<float>(r)的基础上偏移c*3+i

cv::Mat x(5, 4, CV_32FC3, cv::Scalar(0.0, 1.1, 2.2));for (int r = 0; r < x.rows; r++)
{for (int c = 0; c < x.cols; c++){  for (int i = 0; i < 3; i++){      std::cout<<a.ptr<float>(r)[c*3+i]<<std::endl;    }}
}

使用Mat进行各种矩阵元素级运算:

cv::Mat a(3,2,CV_8UC1,cv::Scalar(127));
cv::Mat b(3,2,CV_8UC1,cv::Scalar(128));
cv::Mat mask(3,2,CV_8UC1,255);//默认全体操作double alpha;
double beta;
cv::Mat c;cv::add(a,b,c,mask); // a+b 元素级相加,结果放到c,下面的类似
cv::scaleAdd(a, alpha, b, c, mask); // a*alpha+b, 元素级相加,其中一个矩阵带缩放
cv::addWeighted(a, alpha, b, beta, c, mask); // a*alpha+b*beta, 元素级相加,两个矩阵分别带缩放系数 (还可以带偏移gamma)
cv::subtract(a,b,c,mask); // 元素级想减
cv::abs(a,c); // 取绝对值
cv::absdiff(a,b,c); // 元素级相减取绝对值
cv::multiply(a,b,c,mask); // 元素级乘法
cv::divide(a,b,c,mask); // 元素级除法
//类似的操作还有log,sqrt,exp,pow,min,maxcv::compare(a,b,c, cv::CMP_GT); // 元素级比较大小,结果存放在c中,条件满足则为255,否则为0,就是说c是一个元素类型CV_8UC1的矩阵
//条件关系 CMP_GT 大于 --- CMP_GE 大于等于 --- CMP_LT 小于 --- CMP_LE 小于等于 --- CMP_EQ 等于 --- CMP_NE不等于//元素级逻辑运算cv::bitwise_or(a,b,c,mask);//类似的还有bitwise_and等,注意这个不仅仅是元素级,还是位运算,例如a某个元素是128,b对应位置的元素是0,则它们进行bitwise_or的结果,对应位置是128
//如果b对应位置的元素是1,那么结果对应位置就是129(因为128最后一位是0,和1的最后一位(也就是1)相或后得到1,128的前边的位数都保留了,得到129)
//同理如果a的元素是129,b对应元素是1,那么结果该位置还是129

C++实现矩阵的创建和运算:

#include <iostream>
#include <malloc.h>
#include <stdio.h>
using namespace std;typedef struct
{//结构体int row,col;//二维指针,目的是动态分配内存float **matrix;
} Matrix;typedef struct
{char *name;char *number;
} Student;Matrix CreateMatrix()
{Matrix m;int row,col;cout << "输入行数与列数:" << endl;cin >> row >> col;float **enterMatrix ;enterMatrix=(float**) malloc(row*sizeof(float*)) ;for(int i=0; i<row; i++)enterMatrix[i] = (float *)malloc(col * sizeof(float));cout<<"输入你的矩阵:"<<endl;for(int i=0; i<row; i++){for(int j=0; j<col; j++){cin >> enterMatrix[i][j];}}m.col = col;m.row = row;m.matrix = enterMatrix;return m;
}//初始化一个行为row列为col矩阵
Matrix InitMatrix(int row,int col)
{Matrix m;float **matrix ;matrix=(float**) malloc(row*sizeof(float*)) ;for(int i=0; i<row; i++)matrix[i] = (float *)malloc(col * sizeof(float));for(int i=0; i<row; i++){for(int j=0; j<col; j++){matrix[i][j] = 0;}}m.col = col;m.row = row;m.matrix = matrix;return m;
}Matrix add(Matrix m1, Matrix m2)
{for(int i=0; i<m1.row; i++){for(int j=0; j<m1.col; j++){m1.matrix[i][j] = m1.matrix[i][j] +m2.matrix[i][j];}}return m1;
}Matrix sub(Matrix m1, Matrix m2)
{for(int i=0; i<m1.row; i++){for(int j=0; j<m1.col; j++){m1.matrix[i][j] = m1.matrix[i][j] -m2.matrix[i][j];}}return m1;
}int calRowCol(Matrix M1,Matrix M2,int row,int col)//row为M1的行 col为m2的列
{int result = 0;int same = M1.col;for(int j=0; j<same; j++){result+=M1.matrix[row][j]*M2.matrix[j][col];}return result;
}Matrix Mul(Matrix m1, Matrix m2)
{Matrix result = InitMatrix(m1.row,m2.col);for(int i=0; i<m1.row; i++){for(int j=0; j<m2.col; j++){result.matrix[i][j] = calRowCol(m1,m2,i,j);}}return result;
}Matrix numMul(Matrix m, int num)
{cout<<"数值:"<<num<<endl;for(int i=0; i<m.row; i++){for(int j=0; j<m.col; j++){m.matrix[i][j] = m.matrix[i][j]*num;}}return m;
}Matrix printMatrix(Matrix m)
{for(int i=0; i<m.row; i++){for(int j=0; j<m.col; j++){cout << m.matrix[i][j] << "  ";}cout<<endl;}
}int main()
{int num = 0;do{cout<<"*************************************\n";cout<<"*              菜单                 *\n";cout<<"*          1.矩阵相加               *\n";cout<<"*          2.矩阵相减               *\n";cout<<"*          3.矩阵相乘               *\n";cout<<"*          4.矩阵数乘               *\n";cout<<"*          5.退出                   *\n";cout<<"*************************************\n";cin>>num;if(1 == num|| 2 == num || 3 == num){cout<<"请输入矩阵1"<<endl;Matrix m1 = CreateMatrix();cout<<"请输入矩阵2"<<endl;Matrix m2 = CreateMatrix();cout<<"两矩阵为"<<endl;printMatrix(m1);cout<<endl;printMatrix(m2);switch(num){case 1:{if(m1.col!=m2.col || m1.row!=m2.row){cout<<"行列不同"<<endl;}else{cout<<"结果为:"<<endl;printMatrix(add(m1,m2));}break;}case 2:{if(m1.col!=m2.col || m1.row!=m2.row){cout<<"参数错误"<<endl;}else{cout<<"结果为:"<<endl;printMatrix(sub(m1,m2));}break;}case 3:{if(m1.col!=m2.row){cout<<"参数错误"<<endl;}else{cout<<"结果为:"<<endl;printMatrix(Mul(m1,m2));}break;}default:break;}}else if(4 == num){int number = 1;cout<<"请输入矩阵"<<endl;Matrix m = CreateMatrix();cout<<"请输入数值"<<endl;cin>>number;cout<<"矩阵为:"<<endl;printMatrix(m);cout<<"数值为:"<<endl;cout<<number<<endl;printMatrix(numMul(m,number));}cout<<"按回车继续....";getchar();getchar();system("cls");}while(1 == num|| 2 == num || 3 == num ||4 == num);return 0;
}

zeros()函数创建Mat和任意颜色创建Mat

Mat dst = Mat::zeros(imgSmall.size(), CV_8UC3);  //创建一个三通道每个元素都为0的图片
dst = cv::Mat(imgSmall.rows, imgSmall.cols, CV_8UC3, Scalar(255, 255, 255));  //创建一个三通道每个元素都为255的图片或者其他任意颜色的图片

【如果对您有帮助,交个朋友给个一键三连吧,您的肯定是我博客高质量维护的动力!!!】 

  相关解决方案