【slam十四讲_相机与图像】—ch5.mageBasics.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
            clock_t time_stt=clock();
            在执行相关算法处理之后计算用时: (clock()-time_stt)/(double)CLOCKS_PER_SEC(见p46)
2. 头文件为:#include
              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();    
4.复制图像的方式:
    1.直接赋值:在这种方式下的赋值,一旦对复制后的图像进行更改,则原图像也会改变
    2.使用clone函数赋值:对复制后的图像更改不会影响到原图像
5. 遍历图像像素的方法:
  参考:1.https://blog.csdn.net/keith_bb/article/details/53071133
  对图像像素进行遍历时共有三种方法: 1). 动态地址计算
                    2). 迭代器iterator 
                    3). C操作符[] (指针方式访问)
示例:
  #include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>

using namespace std;
using namespace cv;

void colorReduceAt(Mat& dstImageAt,int div);
void colorReduceIterator(Mat &dstImageIterator, int div);
void colorReducePtr(Mat &dstImagePtr, int div);

int main(int argc,char** argv)
{
    Mat srcImg=imread(argv[1]);
    if(argc!=1)
    {
        cout<<"usage:./total lena.png"<<endl;
    }
    imshow("lena.png",srcImg);

    //声明处理后图像变量
    Mat dstImageAt,dstImageIterator,dstImagePtr;
    dstImageAt=srcImg.clone();
    dstImageIterator=srcImg.clone();
    dstImagePtr=srcImg.clone();

    int div=50;

    //声明时间变量
    double timeAt,timeIterator,timePtr;

    //at()
    timeAt=static_cast<double>(getTickCount());
    colorReduceAt(dstImageAt,div);
    timeAt=((double)getTickCount()-timeAt)/getTickFrequency();
    imshow("dstImageAt_lena.png",dstImageAt);
    cout<<"使用at()动态地址计算耗时:"<<timeAt<<"s"<<endl<<endl;

    //iterator
    timeIterator=static_cast<double>(getTickCount());
    colorReduceAt(dstImageIterator,div);
    timeIterator=((double)getTickCount()-timeIterator)/getTickFrequency();
    imshow("dstImageIterstor_lena.png",dstImageIterator);
    cout<<"使用iterator迭代器计算耗时:"<<timeIterator<<"s"<<endl<<endl;

    //ptr
    timePtr=static_cast<double>(getTickCount());
    colorReducePtr(dstImagePtr,div);
    timePtr=((double)getTickCount()-timePtr)/getTickFrequency();
    imshow("dstImagePtr_lena.png",dstImagePtr);
    cout<<"使用ptr指针计算耗时:"<<timePtr<<"s"<<endl<<endl;

    waitKey(0);
}

//使用at动态地址计算方式
//用函数at()来实现对矩阵中某个像素值进行读取
//以及进行赋值操作
void colorReduceAt( Mat &dstImageAt, int div)
{
    int rowNumber=dstImageAt.rows;//获取图像行数
    int colNumber=dstImageAt.cols;//获取图像列数

    //对每个像素进行处理
    for(int i=0;i<rowNumber;++i)
    {
        for(int j=0;j<colNumber;++j)
        {
            dstImageAt.at<Vec3b>(i,j)[0]=dstImageAt.at<Vec3b>(i,j)[0]/div*div;//Blue
            dstImageAt.at<Vec3b>(i,j)[0]=dstImageAt.at<Vec3b>(i,j)[0]/div*div;//Green
            dstImageAt.at<Vec3b>(i,j)[0]=dstImageAt.at<Vec3b>(i,j)[0]/div*div;//Red
        }
    }
}

//使用iterator迭代器方式
void colorReduceIterator(Mat &dstImageIterator, int div)
{
    MatIterator_<Vec3b> imageIt=dstImageIterator.begin<Vec3b>();//获取迭代器初始位置
    MatIterator_<Vec3b> imageEnd=dstImageIterator.end<Vec3b>();//获取迭代器结束位置

    for(;imageIt!=imageEnd;++imageIt)
    {
        (*imageIt)[0]=(*imageIt)[0]/div*div;//Blue
        (*imageIt)[1]=(*imageIt)[1]/div*div;//Green
        (*imageIt)[2]=(*imageIt)[2]/div*div;//Red
    }
}

//使用ptr指针
void colorReducePtr(Mat &dstImagePtr, int div)
{
    int rowNumber=dstImagePtr.rows;
    int colNumber=dstImagePtr.cols;

    for(int i=0;i<rowNumber;++i)
    {
        uchar* pixelPtr=dstImagePtr.ptr<uchar>(i);//获取矩阵每行首地址
        for(int j=0;j<colNumber;++j)
        {
            pixelPtr[j]=pixelPtr[j]/div*div;
        }
    }
}

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

从上述的运行结果中,我们可以看出指针方式是最快的处理方式,而迭代器的方式相对最慢。但是使用迭代器是较为安全的访问方式。
如果需要对图像像素进行遍历,不推荐使用at()函数,因为使用这个函数其效率不高,但是其可读性较好。

参考:1.https://www.cnblogs.com/cc111/p/9276411.html

声明:本人写博客只为记录学习点滴,加深印象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值