概述
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、读文件所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复