我是靠谱客的博主 有魅力黑夜,最近开发中收集的这篇文章主要介绍SLAM14讲程序学习收集1、读文件,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

1、读文件

fscanf

FILE *fp;
while(!feof(fp))
{
fscanf(fp,"%s%d%lf",a,&b,&c);//这里%s对应的a不需要加上取地址符号&,因为a为数组名称,其本身就表示该数组的首地址
printf("%s%d%lf",a,b,c)
}

imread——图片

#include <iostream>
#include <boost/format.hpp>
#include <opencv2/opencv.hpp>
using namespace std;

int main(){
	//%06d, 6个占位符,从后面补入数字
    boost::format fim("./%06d.png");

    for (int i = 1; i < 6; i++){
        cv::Mat img = cv::imread((fim % i).str(),0);
        cv::imshow("img",img);
        cv::waitKey(0);
    }
    /*string image_file = "./000001.png";
    cv::Mat img = cv::imread(image_file);
    cv::imshow("img",img);
    cv::waitKey(0);
     */
}

fopen

https://www.cnblogs.com/zhengxl5566/p/8951852.html

1 /* fopen example */
 2 #include <stdio.h>
 3 int main ()
 4 {
 5   FILE * pFile;
 6   pFile = fopen ("myfile.txt","w");
 //FILE *fptr = fopen(filename.c_str(), "r");c_str文件名字符串
 7   if (pFile!=NULL)
 8   {
 9     fputs ("fopen example",pFile);
10     fclose (pFile);
11   }
12   return 0;
13 }

OpenCV4 imread 不一样了

需要头文件,否则CV_LOAD_IMAGE_UNCHANGED会报错

#include "opencv2/imgcodecs/legacy/constants_c.h"
image = cv::imread(filenames[i],CV_LOAD_IMAGE_UNCHANGED);

int *pa=new int[size]

表示创建动态数组pa[10]

BAL数据集

<num_cameras> <num_points> <num_observations>
<camera_index_1> <point_index_1> <x_1> <y_1>
...
<camera_index_num_observations> <point_index_num_observations> <x_num_observations> <y_num_observations>
<camera_1>
...
<camera_num_cameras>
<point_1>
...
<point_num_points>

2、OpenCV命令

2.1图像大小设置 Size

Size sz(cvRound((float)image.cols*scale), cvRound((float)image.rows*scale));

2.2 图像转换

RGB到灰度图

cvtColor(mImGray,mImGray,CV_RGB2GRAY);

2.3 Mat::reshape

在opencv中,reshape函数比较有意思,它既可以改变矩阵的通道数,又可以对矩阵元素进行序列化,非常有用的一个函数。

函数原型:

Mat Mat::reshape(int cn, int rows=0) const

参数比较少,但设置的时候却要千万小心。

cn: 表示通道数(channels), 如果设为0,则表示保持通道数不变,否则则变为设置的通道数。

rows: 表示矩阵行数。 如果设为0,则表示保持原有的行数不变,否则则变为设置的行数。

2.4.1 cvMat() 函数

将普通数组转化为CvMat

double a[12]  =  {  1, 2,3, 4,            

                  5, 6, 7, 8,                

                  9,10, 11, 12 };

CvMat mat = cvMat( 3, 4, CV_64FC1, a );

2.4.2 CvMat 格式自动跳行和指针加速赋值(或遍历)

void PnPsolver::fill_M(CvMat * M,
		  const int row, const double * as, const double u, const double v)
{
	//M为 2 × 12矩阵,row为2的倍数
  // 第一行起点
  double * M1 = M->data.db + row * 12;  //第一行
  // 第二行起点
  double * M2 = M1 + 12;  //直接调到第二行,而不用索引

  // 
  for(int i = 0; i < 4; i++) {
    M1[3 * i    ] = as[i] * fu;
    M1[3 * i + 1] = 0.0;
    M1[3 * i + 2] = as[i] * (uc - u);

    M2[3 * i    ] = 0.0;
    M2[3 * i + 1] = as[i] * fv;
    M2[3 * i + 2] = as[i] * (vc - v);
  }
}

2.5 Ptr和ptr的不同

opencv中的Ptr指其使用的智能指针,指的是Template class for smart reference-counting pointers(智能指针模板类)

ptr是在访问图片中像素时的操作,如image.ptr(5),指的是访问image图片的第6行像素值。

作者:sunsimple
链接:https://www.jianshu.com/p/97b154d0e63b

2.6 OpenCV极线计算、图像绘制圆和直线、图像的拼接

    Mat FindFundamental = findFundamentalMat(point1, point2, FM_8POINT);
    vector<Point3f> epilines1, epilines2;
    computeCorrespondEpilines(point1,1,FindFundamental,epilines1);
    computeCorrespondEpilines(point2,2,FindFundamental,epilines2);
    cv::RNG &rng = theRNG();
    for (int i = 0; i < 10; ++i) {
        //随机产生颜色
        Scalar color = Scalar(rng(255), rng(255), rng(255));
        circle(image1, point1[i], 5, color, 3);
        //绘制外极线的时候,选择两个点,一个是x=0处的点,一个是x为图片宽度处
        line(image1, cv::Point(0, -epilines2[i].z / epilines2[i].y),Point(image1.cols, -(epilines2[i].z + epilines2[i].x * image1.cols) / epilines2[i].y), color);

        circle(image2, point2[i], 5, color, 3);
        line(image2, cv::Point(0, -epilines1[i].z / epilines1[i].y),Point(image2.cols, -(epilines1[i].z + epilines1[i].x * image2.cols) / epilines1[i].y), color);
    }

    Mat cmtimage = Mat(Size(image1.cols*2, image1.rows*2),image1.type(), Scalar(0));
    cmtimage(Rect(0,0,image1.cols,image1.rows)) += image1;
    cmtimage(Rect(image1.cols, 0,image1.cols,image1.rows)) += image2;
    imwrite("./result.png", cmtimage);

2.7 遍历图像每一行,从而遍历每个通道

    for(int v=0; v<im_temp.rows; v++)
    {
        for(int u=0; u<im_temp.cols; u++)
        {
            //指针说明dstRow改变了,im_dst的值也会发生改变
            const uchar* tempRow = im_temp.ptr(v);
            uchar* dstrow = im_dst.ptr(v);
            if(tempRow[u*3]!=0)
            {
                dstrow[u*3] = tempRow[u*3];
                dstrow[u*3+1] = tempRow[u*3+1];
                dstrow[u*3+2] = tempRow[u*3+2];
            }
        }
    }

3、SLAM工具

3.1 evo分析工具,orghttps://github.com/MichaelGrupp/evo/wiki/Plotting在这里插入图片描述

4、SLAM调试

ORBS_SLAM2实时单目调试

1、ROS和相机的调试
https://blog.csdn.net/xjtcly/article/details/103464254#t9
2、实时调试命令
https://blog.csdn.net/weixin_43243788/article/details/90703625

5、C++容器使用

5.1容器的遍历

for(vector<MapPoint*>::iterator vit=vpMP.begin(), vend=vpMP.end(); vit!=vend; vit++)

5.2 容器使用

5.2.1 lower_bound()和 upper_bound()

https://blog.csdn.net/qq_40160605/article/details/80150252
lower_bound( )和upper_bound( )都是利用二分查找的方法在一个排好序的数组中进行查找的。

在从小到大的排序数组中,lower_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。

upper_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。

5.2.1.1 vector< vector >使用

int main()
{
    vector< vector<int> > double_vecotr;
    for (int i = 0; i < 10; ++i) {
        vector<int> vector1;
        for (int j = 8; j != 0; --j) {
            vector1.push_back(j);
        }
        double_vecotr.push_back(vector1);
    }
    //vector由左到右调用即可
    cout << "order[i][j]: " << double_vecotr[0][1] << endl;
    return 0;
}

5.2.1 list.pop_front()

删除第一个元素并自动指向下一个元素

mlNewKeyFrames.pop_front();  

5.2.2 erase()妙用——迭代到下一个元素

list<MapPoint*>::iterator lit = mlpRecentAddedMapPoints.begin();
lit = mlpRecentAddedMapPoints.erase(lit);//删除了自己,迭代器自动指向下一个元素

6指针和引用

6.1 double * a = alphas + 4 * i; a改变导致alphas改变

//double * a = alphas + 4 * i;                  // a指向第i个控制点系数alphas的首地址
//todo 验证上述改变a的值 是否会投映到alphas

#include <iostream>

using namespace std;

int main()
{
    double alphas[1000];
    for (int j = 0; j < 300; ++j) {
        double * a = alphas + 3 * j;
        for (int i = 0; i < 3; ++i) {
            a[i] = i;
            cout << alphas[j + i] << endl;
        }
    }

    return 0;
}

7、PCL点云库使用
读取pcd文件

pcl_viewer ./test.pcd

最后

以上就是有魅力黑夜为你收集整理的SLAM14讲程序学习收集1、读文件的全部内容,希望文章能够帮你解决SLAM14讲程序学习收集1、读文件所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(42)

评论列表共有 0 条评论

立即
投稿
返回
顶部