从零开始学习SLAM:openCV

继续跟随《视觉SLAM十四讲》学习SLAM问题,由于理论方面已经有一些研究,主要缺乏的是在LINUX下的实战开发能力,因而从代码开始分析入手,同时对C++11进行回顾。

1. openCV 中的Mat类

Mat类用于存储图像信息,详细信息见 https://docs.opencv.org/3.1.0/d3/d63/classcv_1_1Mat.html ,这里我们主要针对几个常用的点展开来记录。

  1. 类的结构
    Mat是由两个数据部分,包含信息有矩阵的大小,用于存储的方法,矩阵存储的地址等的矩阵头和一个指针,指向包含了像素值的矩阵(可根据选择用于存储的方法采用任何维度存储数据)。矩阵头部的大小是恒定的。然而,矩阵本身的大小因图像的不同而不同,通常是较大的数量级。
  2. 构造函数
    Mat类的默认构造函数为cv::Mat::Mat(),生成一个矩阵并由OpenCV提供的函数(一般是Mat::create() 和 cv::imread() )来分配储存空间。OpenCV使用了引用次数,当进行图像复制和传递时,不再复制整个Mat数据,而只是复制矩阵头和指向像素矩阵的指针,例如:
    / 关于 cv::Mat 的拷贝
    // 直接赋值并不会拷贝数据
    cv::Mat image_another = image;
    // 修改 image_another 会导致 image 发生变化
    image_another ( cv::Rect ( 0,0,100,100 ) ).setTo ( 0 ); // 将左上角100*100的块置零
    cv::imshow ( "image", image );
    cv::waitKey ( 0 );
    
    // 使用clone函数来拷贝数据
    cv::Mat image_clone = image.clone();
    image_clone ( cv::Rect ( 0,0,100,100 ) ).setTo ( 255 );
    cv::imshow ( "image", image );
    cv::imshow ( "image_clone", image_clone );
    cv::waitKey ( 0 );

也就是说直接拷贝拷贝的只是指向数据矩阵的指针,对任意一个指针指向内容的修改会影响其他所有的,销毁时则是每销毁一个引用计数会-1(每copy一次同样会+1),直到计数为0,矩阵数据会被清理。
常用的构造函数还包括

    Mat (int rows, int cols, int type)
 	Mat (Size size, int type)
 	Mat (int rows, int cols, int type, const Scalar &s)
 	Mat (Size size, int type, const Scalar &s)
 	Mat (int ndims, const int *sizes, int type)
 	Mat (int ndims, const int *sizes, int type, const Scalar &s)
 	Mat (const Mat &m)
 	Mat (int rows, int cols, int type, void *data, size_t step=AUTO_STEP)
 	Mat (Size size, int type, void *data, size_t step=AUTO_STEP)
 	Mat (int ndims, const int *sizes, int type, void *data, const size_t *steps=0)
 	Mat (const Mat &m, const Range &rowRange, const Range&colRange = Range::all())
 	Mat (const Mat &m, const Rect &roi)
 	Mat (const Mat &m, const Range *ranges)
  1. 成员函数
    Mat成员函数较常用的包括at(获取某位置的元素值),convertTo(将源文件转化为目标数据格式),clone(复制图像矩阵数据),create(分配矩阵的存储单元),type(获取数据类型),channels(获取通道数)(rows和cols属于Member Data调用不需要加括号),详细的说明可见 https://blog.csdn.net/guyuealian/article/details/70159660

2. 一个方便的读取矩阵txt文件的方式

ifstream fin("文件名.txt");
for ( int i=0; i<矩阵行数; i++ )
{
    double data[矩阵列数] = {0};
    for ( auto& d:data )
        fin>>d;
}

3. 两种常用的访问图像像素的方法

  1. 视觉SLAM十四讲中的方法(使用指针)
for ( size_t y=0; y ( y );  // row_ptr是第y行的头指针
        for ( size_t x=0; x
  1. 使用at
for (int i = 0; i < image.rows; i++) 
	{ 
		for (int j = 0; j(i,j)[0]=image.at(i,j)[0]/div*div+div/2;
			image.at(i,j)[1]=image.at(i,j)[1]/div*div+div/2;
			image.at(i,j)[2]=image.at(i,j)[2]/div*div+div/2;
		} 
	} 

其他方法可以参考 https://blog.csdn.net/xiaowei_cqu/article/details/19839019

你可能感兴趣的:(SLAM学习)