<<视觉slam十四讲>>_ch5 实践部分之imageBasics.cpp的代码解释及总结

1.关于int main(int argc,char** argv)中argc,argv参数的解释

   argc参数表示命令行中参数的个数,其值是在输入命令时由系统按实际参数的个数自动赋值的
      argv参数是字符串指针数组,存放命令行中的参数,长度即为参数个数argc
      其中的第0个参数是程序的全名,之后的参数由用户输入的参数确定

 

2.关于 cv::waitKey(0)的解释:

  在inshow之后必须要有waitKey(k),以便给予足够的时间显示图像,功能是不断刷新图像。waitKey(k)仅对窗口机制起作用,其中k的单位为ms:如果k=0,表示无线等待下去,直到有按键按下,无返回值;如果k>0,表示等待的时间,若在这段时间内没有任何操作则等待结束后返回-1,如在期间输入了字符,则最终返回字符的ASCII码

 

3.像素的表示:

  如果是灰度图,用8位整数(unsigned char)表示一个像素,即表示0~255的值.
       如果是RGB相机的深度图中,由于记录了各个像素与相机之间的距离(单位为毫米),而RGB相机的量程在十几米左右,超过了255,所以用16位整数(unsigned short)表示一个像素,即表示0~65536的值.
       如果是彩色图像,常见的是用三个通道(即red,blue,green三个颜色)表示任意一种色彩,而每个通道占8位,所以用24位表示一个像素.

 

4.给算法计时:
    1).头文件为:#include<ctime>
        clock_t time_stt=clock();
        在执行相关算法处理之后计算用时: (clock()-time_stt)/(double)CLOCKS_PER_SEC(见p46)
    2).头文件为:#include <chrono>
          chrono::steady_clock::time_point t1=chrono::steady_clock::now();

    //...

    //program...

    //...

    chrono::steady_clock::time_point  t2=chrono::steady_clock::now();
       chrono::duration<double> time_used=chrono::duration_cast<chrono::duration<double>>(t2-t1);

  3)opencv计时函数:

     double t=static_cast<double> (getTickCount());

    //...

    //program...

    //...

    t = ((double)getTickCount()-t)/getTickFrequency();    

5.复制图像的方式:
    1.直接赋值:在这种方式下的赋值,一旦对复制后的图像进行更改,则原图像也会改变
    2.使用clone函数赋值:对复制后的图像更改不会影响到原图像

 

6. 遍历图像像素的方法:

  参考:https://blog.csdn.net/keith_bb/article/details/53071133

  对图像像素进行遍历时共有三种方法: 1). 动态地址计算
                    2). 迭代器iterator
                    3). C操作符[] (指针方式访问)

  我们给出一个综合例程:

  1 #include <iostream>
  2 #include <opencv2/core.hpp>
  3 #include <opencv2/highgui.hpp>
  4 
  5 using namespace std;
  6 using namespace cv;
  7 
  8 void colorReduceAt(Mat& dstImageAt,int div);
  9 void colorReduceIterator(Mat &dstImageIterator, int div);
 10 void colorReducePtr(Mat &dstImagePtr, int div);
 11 
 12 int main(int argc,char** argv)
 13 {
 14     Mat srcImg=imread(argv[1]);
 15     if(argc!=1)
 16     {
 17         cout<<"usage:./total lena.png"<<endl;
 18     }
 19     imshow("lena.png",srcImg);
 20 
 21     //声明处理后图像变量
 22     Mat dstImageAt,dstImageIterator,dstImagePtr;
 23     dstImageAt=srcImg.clone();
 24     dstImageIterator=srcImg.clone();
 25     dstImagePtr=srcImg.clone();
 26 
 27     int div=50;
 28 
 29     //声明时间变量
 30     double timeAt,timeIterator,timePtr;
 31 
 32     //at()
 33     timeAt=static_cast<double>(getTickCount());
 34     colorReduceAt(dstImageAt,div);
 35     timeAt=((double)getTickCount()-timeAt)/getTickFrequency();
 36     imshow("dstImageAt_lena.png",dstImageAt);
 37     cout<<"使用at()动态地址计算耗时:"<<timeAt<<"s"<<endl<<endl;
 38 
 39     //iterator
 40     timeIterator=static_cast<double>(getTickCount());
 41     colorReduceAt(dstImageIterator,div);
 42     timeIterator=((double)getTickCount()-timeIterator)/getTickFrequency();
 43     imshow("dstImageIterstor_lena.png",dstImageIterator);
 44     cout<<"使用iterator迭代器计算耗时:"<<timeIterator<<"s"<<endl<<endl;
 45 
 46     //ptr
 47     timePtr=static_cast<double>(getTickCount());
 48     colorReducePtr(dstImagePtr,div);
 49     timePtr=((double)getTickCount()-timePtr)/getTickFrequency();
 50     imshow("dstImagePtr_lena.png",dstImagePtr);
 51     cout<<"使用ptr指针计算耗时:"<<timePtr<<"s"<<endl<<endl;
 52 
 53     waitKey(0);
 54 }
 55 
 56 //使用at动态地址计算方式
 57 //用函数at()来实现对矩阵中某个像素值进行读取
 58 //以及进行赋值操作
 59 void colorReduceAt( Mat &dstImageAt, int div)
 60 {
 61     int rowNumber=dstImageAt.rows;//获取图像行数
 62     int colNumber=dstImageAt.cols;//获取图像列数
 63 
 64     //对每个像素进行处理
 65     for(int i=0;i<rowNumber;++i)
 66     {
 67         for(int j=0;j<colNumber;++j)
 68         {
 69             dstImageAt.at<Vec3b>(i,j)[0]=dstImageAt.at<Vec3b>(i,j)[0]/div*div;//Blue
 70             dstImageAt.at<Vec3b>(i,j)[0]=dstImageAt.at<Vec3b>(i,j)[0]/div*div;//Green
 71             dstImageAt.at<Vec3b>(i,j)[0]=dstImageAt.at<Vec3b>(i,j)[0]/div*div;//Red
 72         }
 73     }
 74 }
 75 
 76 //使用iterator迭代器方式
 77 void colorReduceIterator(Mat &dstImageIterator, int div)
 78 {
 79     MatIterator_<Vec3b> imageIt=dstImageIterator.begin<Vec3b>();//获取迭代器初始位置
 80     MatIterator_<Vec3b> imageEnd=dstImageIterator.end<Vec3b>();//获取迭代器结束位置
 81 
 82     for(;imageIt!=imageEnd;++imageIt)
 83     {
 84         (*imageIt)[0]=(*imageIt)[0]/div*div;//Blue
 85         (*imageIt)[1]=(*imageIt)[1]/div*div;//Green
 86         (*imageIt)[2]=(*imageIt)[2]/div*div;//Red
 87     }
 88 }
 89 
 90 //使用ptr指针
 91 void colorReducePtr(Mat &dstImagePtr, int div)
 92 {
 93     int rowNumber=dstImagePtr.rows;
 94     int colNumber=dstImagePtr.cols;
 95 
 96     for(int i=0;i<rowNumber;++i)
 97     {
 98         uchar* pixelPtr=dstImagePtr.ptr<uchar>(i);//获取矩阵每行首地址
 99         for(int j=0;j<colNumber;++j)
100         {
101             pixelPtr[j]=pixelPtr[j]/div*div;
102         }
103     }
104 } 

     运行结果:  

           

        

    三种遍历像素的方法对比:

         从上述的运行结果中,我们可以看出指针方式是最快的处理方式,而迭代器的方式相对最慢。但是使用迭代器是较为安全的访问方式。

        如果需要对图像像素进行遍历,不推荐使用at()函数,因为使用这个函数其效率不高,但是其可读性较好。

 

posted @ 2018-07-07 09:42  Iridescent18  阅读(904)  评论(0编辑  收藏  举报