zoukankan      html  css  js  c++  java
  • opencv-图像遍历

    利用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();  //创建一个矩阵头(浅拷贝,数据共享),指向指定所有行的数据
        //参数是前闭后开;上面参数指向的是第二行和第三行的数据,不包括第四行
    
        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;



  • 相关阅读:
    简单命令行总结
    [大餐]开发摘记1--我的Fragment通信的框架 | 卖牙膏的芖口钉
    DZNEmptyDataSet的使用
    Java笔记(一)
    mingster.com
    2014新年福利,居然有人将Ext JS 4.1的文档翻译了
    【翻译】Sencha Touch 2入门:创建一个实用的天气应用程序之三
    【翻译】在Ext JS应用程序中使用自定义图标
    【翻译】Siesta事件记录器入门
    【翻译】使用新的Sencha Cmd 4命令app watch
  • 原文地址:https://www.cnblogs.com/liming19680104/p/15370674.html
Copyright © 2011-2022 走看看