读入批量图像
读入两帧图像直接使用imread即可,但是读入文件夹内的图像文件夹有点复杂。
一、十四讲第八章使用LK光流法
在视觉SLAM十四讲第八章使用LK光流法时,第一帧图像提取FAST特征点,之后的帧使用LK跟踪特征点,需要批量导入图像。
这里提供的方式如下:
string path_to_dataset="../TUM";
string associate_file=path_to_dataset+"/associate.txt";// string+"" 复合
ifstream fin(associate_file); //string转流
string rgb_file, depth_file,time_rgb,time_depth;
for (int index=0;index<100;index++)
{
fin>>rgb_file>>depth_file>>time_rgb>>time_depth;// 流的功能>>
color=cv::imread(path_to_dataset+"/"+rgb_file);// imread参数为string类型
depth=cv::imread(path_to_dataset+"/"+depth_file,-1);
}
1、其中,associate.txt对depth和rgb图像的采集时间进行配对,时间上对齐。
运行:python associate.py rgb.txt depth.txt > associate.txt
2、imread(flag); 彩色图像为8位3通道,深度图为16位单通道图像。
flags = 1:imread按三通道方式读入图像,即彩色图像
flags = 0:imread按单通道的方式读入图像,即灰白图像
flags = -1:imread按解码得到的方式读入图像
3、groundtruth.txt为标准轨迹,外部运动捕捉系统采集到的相机位姿。(time,tx,ty,tz,qx,qy,qz,qw)
二、VINS-mono读取图像
void PubImuData()
{
string sImu_data_file = sConfig_path + "MH_05_imu0.txt";// string+""复合
ifstream fsImu;// 流形式fsImu
fsImu.open(sImu_data_file.c_str());//string转char*
if (!fsImu.is_open())
{
cerr << "Failed to open imu file! " << sImu_data_file << endl;
return;
}
std::string sImu_line;// 每一行imu数据string类型
double dStampNSec = 0.0;
Vector3d vAcc;
Vector3d vGyr;
while (std::getline(fsImu, sImu_line) && !sImu_line.empty()) // read imu data,getline出来的是string形式
{
std::istringstream ssImuData(sImu_line);// string转流形式
ssImuData >> dStampNSec >> vGyr.x() >> vGyr.y() >> vGyr.z() >> vAcc.x() >> vAcc.y() >> vAcc.z();
// cout << "Imu t: " << fixed << dStampNSec << " gyr: " << vGyr.transpose() << " acc: " << vAcc.transpose() << endl;
pSystem->PubImuData(dStampNSec / 1e9, vGyr, vAcc);
usleep(5000*nDelayTimes);
}
fsImu.close();
}
void PubImageData()
{
string sImage_file = sConfig_path + "MH_05_cam0.txt";// string+""复合
cout << "1 PubImageData start sImage_file: " << sImage_file << endl;
ifstream fsImage;// 流形式
fsImage.open(sImage_file.c_str());//string转char*
if (!fsImage.is_open())
{
cerr << "Failed to open image file! " << sImage_file << endl;
return;
}
std::string sImage_line;
double dStampNSec;
string sImgFileName;
// 循环读取每一行getline出来为string类型
while (std::getline(fsImage, sImage_line) && !sImage_line.empty())
{
std::istringstream ssImuData(sImage_line);//流文件
ssImuData >> dStampNSec >> sImgFileName;
// cout << "Image t : " << fixed << dStampNSec << " Name: " << sImgFileName << endl;
string imagePath = sData_path + "cam0/data/" + sImgFileName;
Mat img = imread(imagePath.c_str(), 0);
if (img.empty())
{
cerr << "image is empty! path: " << imagePath << endl;
return;
}
pSystem->PubImageData(dStampNSec / 1e9, img);
// cv::imshow("SOURCE IMAGE", img);
// cv::waitKey(0);
usleep(50000*nDelayTimes);
}
fsImage.close();
}
三、简单的视觉里程计
在实现里,需要读入KITTI的图像。
要求:图像为顺序排列1、2、3....
char filename[100];
for(int index=2;index<100;index++)
{
sprintf(filename,"/home/avisingh/Datasets/KITTI_VO/00/image_2/%06d.png",index);
Mat currImage_c=imread(filename);
cvtColor(currImage_c,currImage,COLOR_BGR2GRAY);
}
1、sprintf()把格式化的数据写入某个字符串中
2、照片格式为000011.png,所以这里用sprintf(filename,"../%06d.png",index)形式,字长6位,不够的前面补零
相同效果的是:
stringstream ss;
ss << "../" << setw(6) << setfill('0') << index<< ".png";
Mat img(imread(ss.str(),0));
切割视频
#include <iostream>
#include <vector>
#include "opencv2\highgui\highgui.hpp"
#include <string>
#include <iomanip>//setw和setfill要用
using namespace std;
using namespace cv;
void video2image(string video, string path)
{
VideoCapture capture(video);
if (!capture.isOpened())
{
cerr << "Failed to open a video" << endl;
return;
}
//设置开始帧、结束帧、当前帧初始化为初始帧
long frameToStart = 40;
int frameToStop = 200;
long currentFrame = frameToStart;
Mat frame;
int num = 1;
string filename;
bool stop = false;//标志位
while (!stop)
{
capture >> frame;//视频流读入帧中
if (frame.empty())//读完,直接break
break;
stringstream str;//以流的形式
str << path << setw(5) << setfill('0') << num << ".jpg";//命名从1开始计数
cout << "now is reading" << currentFrame << "." << endl;
imshow("Extractedframe", frame);
cout << "now is writing" << currentFrame << "." << endl;
imwrite(str.str(), frame);
//按下ESC或者到达指定的结束帧后退出读取视频
if ( currentFrame > frameToStop)
{
stop = true;
}
num++;//命名从1开始计数
currentFrame++;//当前帧计数
}
capture.release();//关闭视频文件
waitKey(0);
}
int main(int argc, char** argv)
{
string videoFromfile = "./2.avi"; //读取视频
string Imagespath = "./2/"; // 保存图片的文件夹路径一定要有,因为OpenCV不会自动创建文件夹
video2image(videoFromfile, Imagespath);
return 0;
}