1、cv::Mat
现有的常见的数组元素访问方式有三种:
- at函数方式访问
//定义2行2列,CV_8UC1型的 Mat cv::Mat mat(2,2,CV_8UC1); //at成员函数方式访问 mat 元素 uchar p = mat.at<uchar>(0,1); //读0行1列元素 mat.at<uchar>(1,0) = 128; //写1行0列元素
比较直观,但是需要函数调度开销,效率较低
- iteration迭代器方式访问
//定义2行2列,CV_8UC1型的 Mat cv::Mat mat(2,2,CV_8UC1); //定义mat的数据迭代器 cv::MatIterator_<uchar> iter = mat.begin(); //迭代器方式访问 for (int i = 0; i < 2; i++) cout << *(iter++) << endl;
也涉及函数调度,效率一般
- ptr指针访问
//定义2行2列,CV_8UC3型的 Mat cv::Mat roi(2,2,CV_8UC3); //遍历roi所有元素 for (int i = roi.rows-1; i >= 0; i--) { //roi中行元素的首地址储存可能不连续 unsigned char *ptr = roi.ptr<unsigned char>(i); for (int j = roi.cols-1; j >= 0; j--) { ptr[3 * j + 0] = 0; //roi(i,j)的第一通道元素 ptr[3 * j + 1] = 255; //roi(i,j)的第二通道元素 ptr[3 * j + 2] = 0; //roi(i,j)的第三通道元素 } }
mat最快的访问方式,也是opencv推荐的访问方式(二维数组)。这里需要注意,mat数据中,不同行的储存可能是不连续的。行间是否连续可以通过 roi.isContinus() 来获得。
-
extern int* index; //需要访问元素的下标构成的数组 matdataType* elementPointer ; //被访问元素的指针 uchar* tempPointer = mat.data; //临时指针,用于偏移到被访问指针 for(int i=0;i<mat.dims,i++) tempPointer += index[i]*mat.step[i]; //偏移指针 elementPointer = (matdataType*)tempPointer; //地址强制转化
-
代数运算
cv::Mat a,b,c;
/*矩阵级运算*/
c = a + b; //矩阵加法
c = a - b; //矩阵减法
c = a + 1; //矩阵数加,位置可互换
c = a - 1; //矩阵数减,位置可互换
c = a * 1; //矩阵数乘,位置可互换
c = a * b; //矩阵乘,限二维单通道矩阵
c = a.inv(); //矩阵求逆,限二维单通道矩阵
c = a.t(); //矩阵转置,限二维单通道矩阵
cv::Scalar trace = cv::trace(a); //矩阵求迹
double det = cv::determinant(a); //矩阵行列式,要求a为单通道浮点型矩阵
cv::eigen(a,eigenValue,eigenVector); //对称单通道浮点型矩阵a的特征值特征向量特征向量
//eigenValue与eigenVector均为cv::Mat型变量,eigenValue存放了特征值,
//行向量eigenVector[m]对应eigenValue[m],也就是有如下关系成立:
//src*eigenvectors.row(i).t() = eigenvalues.at<srcType>(i)*eigenvectors.row(i).t()
cv::solve(a,b,c); //求解线性方程 A*C = B 中C的最佳值。C与B规模相同,为多个列向量,A必须为方阵
/*元素级运算*/
//元素级代数运算
cv::multiply(a,b,c,2); //矩阵元素相乘并放大给定的因子
cv::divide(a,b,c); // c=a./b,逐元素除法
cv::exp(a,c); //逐元素求自然底数为底的指数
cv::log(a,c); //逐元素求自然底数为底的对数
cv::pow(a,2,c); //逐元素求指定数的幂次方,注意,对a中非整数对象,则先取绝对值再幂次方
cv::phase(a,b,c); //c = arctan2(b,a);逐元素运算
//不等运算,逐元素比较,返回0\255矩阵
c = a > b;
c = a >= b;
c = a < b;
c = a <= b;
c = a == b;
//矩阵元素位运算
c = a & b;
c = a | b;
c = a ^ b;
c = ~a;
c = a & 1;
//按元素求绝对值
c = cv::abs(a);
//矩阵元素比较并取值
c = cv::max(a,b);
c = cv::max(a,1);
c = cv::min(a,b);
c = cv::min(a,1);
cv::Scalar sum = cv::sum(a); //矩阵元素求和(适用于多通道)
cv::Scalar means = cv::mean(a); //求a全部元素平均值(适用于多通道)