利用at
单通道
cv::Mat M(5, 4, CV_8UC1); //单通道矩阵--灰度
int ch=M.channels();
std::cerr<<M<<std::endl;
int r=M.rows;
int c=M.cols;
qDebug()<<"行数:"<<r<<";"<<"列数:"<<c<<Qt::endl;
for(int i=0;i<r;i++){ //i是行号
for(int j=0;j<c;j++){ //j是列号
int t=M.at<uchar>(i,j); //返回指点坐标的数据
//无符号数据用uchar;float数据用float
std::cout<<t<<";";
}
std::cout<<std::endl;
}
M.at<uchar>(3,2)=99; //修改指点坐标的值
std::cout<<M<<std::endl;
qDebug()<<"通道数:"<<ch<<Qt::endl;
3通道
cv::Mat M(5, 4, CV_8UC3); //3通道矩阵
int ch=M.channels();
std::cerr<<M<<std::endl;
int r=M.rows;
int c=M.cols;
qDebug()<<"行数:"<<r<<";"<<"列数:"<<c<<Qt::endl;
for(int i=0;i<r;i++){ //i是行号
for(int j=0;j<c;j++){ //j是列号
int t=M.at<cv::Vec3b>(i,j)[0]; //返回指点坐标的B值
//注意:用cv::Vec3b;i和j确定像素点;[]里确定哪个通道
int t1=M.at<cv::Vec3b>(i,j)[1]; //返回指点坐标的G值
int t2=M.at<cv::Vec3b>(i,j)[2]; //返回指点坐标的R值
std::cout<<t<<","<<t1<<","<<t2<<";";
}
std::cout<<std::endl;
}
M.at<cv::Vec3b>(3,2)[1]=99; //修改指点坐标的G值
std::cout<<M<<std::endl;
qDebug()<<"通道数:"<<ch<<Qt::endl;
利用指针:优点效率高点
cv::Mat M(5, 4, CV_8UC3); //3通道矩阵
int ch=M.channels();
int nr=M.rows;
int c=M.cols;
int nl=c*ch; //nl是数据列数
//注意:M.cols是像素点列数,而每个像素点分成RGB三个数据,所以数据列数=像素点列数*通道数
std::cerr<<M<<std::endl;
uchar p01 = M.ptr<uchar>(0)[2]; //返回指定行指定数据列的数值
//()里是行号,[]里是列号
uchar* p0 = M.ptr<uchar>(0); //返回指定行的首地址
uchar pp01=p0[2]; //返回指针指定行的指定数据列的数值
M.ptr<uchar>(0)[2]=99; //修改指定行指定数据列的数值
p0[1]=88; //修改指针指定行的指定数据列的数值
std::cerr<<M<<std::endl;
qDebug()<<"通道数:"<<ch<<Qt::endl;
qDebug()<<p01<<Qt::endl;
qDebug()<<pp01<<Qt::endl;
连续矩阵
一行数据肯定是连续的,但是行与行之间不一定是连续的
一般用Mat::creat()创建的矩阵都是连续的,但是也不绝对,依然需要判断才可以进行连续性操作。而从图像中截取的图像通常是不连续的,如果想将其转换为连续存储,可以用clone进行拷贝一份
m*n的数据就是需要判断连续性的。如果数据存储是连续的,可以将图像看出一个一维数组。否则只能用二维数据方式进行访问
cv::Mat M(5, 4, CV_8UC3);
bool b=M.isContinuous(); //判断行与行之间的储存是否连续
std::cerr<<M<<std::endl;
int nl=M.rows*M.cols*M.channels(); //连续矩阵可以看做一行;总列数=行数*像素点列数*通道
if(b==true){
for(int j=0;j<nl;j++){
uchar t = M.ptr<uchar>(0)[j]; //返回指定位置的数据
//连续矩阵看做一行,所以行号是0
qDebug()<<t;
}
qDebug()<<Qt::endl;
}
M.ptr<uchar>(0)[1]=99; //修改指定位置的值
std::cerr<<M<<std::endl;
qDebug()<<b<<Qt::endl;
利用迭代器
cv::Mat M(5, 4, CV_8UC3);
std::cerr<<M<<std::endl;
cv::Mat MM(5, 4, CV_8UC3);
std::cerr<<MM<<std::endl;
//非常量迭代器--通过迭代器可以修改数据
cv::Mat_<cv::Vec3b>::iterator it1 = M.begin<cv::Vec3b>(); //图像左上角位置的迭代器--方式一
cv::MatIterator_<cv::Vec3b> it = M.begin<cv::Vec3b>(); //图像左上角位置的迭代器--方式二
cv::MatIterator_<cv::Vec3b> itend = M.end<cv::Vec3b>(); //图像末尾位置的迭代器
//常量迭代器--通过迭代器不能修改数据
cv::Mat_<cv::Vec3b>::const_iterator itt1=MM.begin<cv::Vec3b>();//方式一
cv::MatConstIterator_<cv::Vec3b> itt = MM.begin<cv::Vec3b>(); //方式二
cv::MatConstIterator_<cv::Vec3b> ittend=MM.end<cv::Vec3b>();
int i=0,i1=0,i2=0;
for (; it != itend; it++,itt++){
i=(*it)[0]; //返回迭代器所指像素点的B值
//*it 表示迭代器所指的像素点
i1=(*it)[1]; //返回迭代器所指像素点的G值
i2=(*it)[2]; //返回迭代器所指像素点的R值
std::printf("%u,%u,%u;",i,i1,i2);
//修改M的值;把MM的值给M
(*it)[0]=(*itt)[0];
(*it)[1]=(*itt)[1];
(*it)[2]=(*itt)[2];
}
std::cerr<<M<<std::endl;
块操作
行列操作
cv::Mat M(5, 4, CV_8UC3);
std::cerr<<M<<std::endl;
cv::Mat mRow=M.row(0); //创建一个矩阵头(浅拷贝,数据共享),指向指定行的数据
//mRow是1行M.cols*M.channels()列的矩阵
cv::Mat mCol=M.col(0); //创建一个矩阵头(浅拷贝,数据共享),指向指定像素列的数据
//mCol是M.rows行M.channels()列的矩阵
cv::Mat mR = M.rowRange(1,3).clone(); //参数是前闭后开;上面参数指向的是第二行和第三行的数据,不包括第四行
//M.rowRange(1,3) 创建一个矩阵头(浅拷贝,数据共享),指向指定所有行的数据
cv::Mat mC = M.colRange(1,3); //创建一个矩阵头(浅拷贝,数据共享),指向指定所有像素列的数据 //参数是前闭后开;上面参数指向的是第二像素列和第三像素列的数据,不包括第四像素列 mRow.ptr<uchar>(0)[1]=99; std::cerr<<mRow<<std::endl; std::cerr<<M<<std::endl;
区域操作
cv::Mat M(10, 9, CV_8UC3);
std::cerr<<M<<std::endl;
cv::Mat MM=M(cv::Rect(1,2,3,5));//创建一个矩阵头(浅拷贝,数据共享),指向指定区域的数据
/*参数1:起始像素点列号--从0开始
参数2:起始像素点行号
参数3:总像素点列数
参数4:总像素点行数
*/
std::cerr<<MM<<std::endl;
MM.at<cv::Vec3b>(3,1)[1]=99;
std::cerr<<MM<<std::endl;
std::cerr<<M<<std::endl;
指向对角线像素点
cv::Mat M(5, 4, CV_8UC3);
std::cerr<<M<<std::endl;
cv::Mat mD=M.diag(0); //创建一个矩阵头(浅拷贝,数据共享),指向M对角线像素点
//参数=0 表示主对角线
std::cerr<<mD<<std::endl;
mD.ptr<uchar>(0)[1]=99;
std::cerr<<M<<std::endl;
std::cerr<<mD<<std::endl;
cv::Mat M(5, 4, CV_8UC3);
std::cerr<<M<<std::endl;
cv::Mat mD=M.diag(1);
//参数n>0 表示对角线向右移动n像素点
std::cerr<<mD<<std::endl;
cv::Mat M(5, 4, CV_8UC3);
std::cerr<<M<<std::endl;
cv::Mat mD=M.diag(-1);
//参数n<0 表示对角线向下移动n像素点
std::cerr<<mD<<std::endl;