最近在处理semanticfusion的数据集时,做了一些数据预处理,记录一下,整个过程与zt同学一起讨论完成,感谢~
程序或多或少后有一些问题,但是终究是可以用了~
这里感谢高博的博客,从这里找到了要入手的方向:
重要的备注:
- 这两张图来自于nyuv2数据集:http://cs.nyu.edu/~silberman/datasets/ 原图格式是ppm和pgm的,被我转成了png格式(否则博客园不让传……)。
- 你可以直接另存为这两个图,也可以到我的git里面获取这两个图。
- 实际Kinect里(或其他rgb-d相机里)直接采到的RGB图和深度图可能会有些小问题:
- 有一些时差(约几到十几个毫秒)。这个时差的存在,会产生“RGB图已经向右转了,怎么深度图还没转”的感觉哦。
- 光圈中心未对齐。因为深度毕竟是靠另一个相机获取的,所以深度传感器和彩色传感器参数可能不一致。
- 深度图里有很多“洞”。因为RGB-D相机不是万能的,它有一个探测距离的限制啦!太远或太近的东西都是看不见的呢。关于这些“洞”,我们暂时睁一只眼闭一只眼,不去理它。以后我们也可以靠双边bayes滤波器去填这些洞。但是!这是RGB-D相机本身的局限性。软件算法顶多给它修修补补,并不能完全弥补它的缺陷。
不过请你放心,在我们给出的这两个图中,都进行了预处理。你可以认为“深度图就是彩色图里每个像素距传感器的距离”啦!
结合semanticfusion提供的bathroom0003,
要入手的方向:将深度图像与彩色图像坐标系对齐
使用toolbox中的project_depth_map这个函数就可以了
这里用matlab,方便查看每个像素值,我是按照semanticfusion里面的对应图像的像素值对应修改的,这个函数输出的图片的每个像素值是1.X,单位是m,但semanticfusion里面的对应图像的像素值是其1000倍,我就简单的变换了一下.
最后输出要注意生成的图片像素值不会被压缩,是原样输出。
(注:代码只供参考,自己需要针对相关问题做出修改)
clear;
clc;
close all;
srcFace = '/home/zebrajiahao/Documents/Dataset/nyu_data_small/depth'; % readFilePath
srcDace = '/home/zebrajiahao/Documents/Dataset/nyu_data_small/red';
fileSavePath = '/home/zebrajiahao/Documents/Dataset/nyu_data_small/qq333'; % savedFilePath
src = srcFace;
src1 = srcDace;
srcsuffix = '.pgm';
src1suffix = '.ppm';
srcsuffixSave = '.png';
files = dir(fullfile(src, strcat('*',srcsuffix)));
files1 = dir(fullfile(src1, strcat('*',src1suffix)));
for file_i = 1 : length(files)
disp(file_i);
srcName = files(file_i).name;
srcName1 = files1(file_i).name;
noSuffixName = srcName(1:end-4);
noSuffixName1 = srcName1(1:end-4);
srcName1 = files(file_i).name;
srcName2 = files1(file_i).name;
pathImgName = sprintf('%s%s%s',src,'/',srcName1);
pathImgName1 = sprintf('%s%s%s',src1,'/',srcName2);
imgDepth = imread(pathImgName);
imgDepth = swapbytes(imgDepth);
rgb = imread(pathImgName1);
[depthOut, rgbOut] = project_depth_map(imgDepth, rgb);
for i = 1 : 480
for j = 1 : 640
if (depthOut(i,j) ~= 0)
depthOut(i,j) = 1000 * depthOut(i,j);
end
end
end
lala = uint16(depthOut);
savePathName=sprintf('%s%s%s%s',fileSavePath,'/',noSuffixName,srcsuffixSave);
imwrite(lala,savePathName,'png','bitdepth',16);
%imwrite(lala,savePathName);
end
%imgDepth = imread('/home/zebrajiahao/Documents/Dataset/nyu_data_small/bathroom_0003/d-1295406963.666549-2770369813.pgm');
%rgb = imread('/home/zebrajiahao/Documents/Dataset/nyu_data_small/bathroom_0003/r-1295406963.675249-2771355972.ppm');
%[depthOut, rgbOut] = project_depth_map(imgDepth, rgb);
%imshow(depthOut);
另外附上bathroom_0XXX.txt文件生成的代码以及修改图片名字的代码
bathroom_0XXX.txt文件生成的代码
代码是有一些问题,但整体勉强可以用 (比如边界控制写得不好,但是懒得改了)
主要问题是原始数据集有很多异常的问题,没有全部解决掉
1.顺序是drdrdrdr是最理想的结果,但有一些会丢失对应的深度图或者彩图,比如drdrrrddrdr这样,程序先判断并删除了连续一样的,还有rdrd顺序的,自己改吧~
2.最前边的序号,是图片的时间戳加1,有时会出现999的问题,会导致序号中出现1000,需要手动删除
#include <iostream>
#include <fstream>
#include <vector>
#include <iomanip>
using namespace std;
// 生成相应格式
int main(int argc, char** argv)
{
if (argc != 3) {
cout << "wrong!" << endl;
return -1;
}
ifstream input(argv[1]);
ofstream output(argv[2]);
string line;
vector<string> svec;
vector<string> news;
vector<string> lala;
while(getline(input, line)) {
if (line[0] != 'a')
svec.push_back(line);
}
for (int i = 0; i != svec.size(); ++i)
{
if (svec[i][0] == 'r' ) {
if ((i+1) != svec.size() && svec[i+1][0] == 'r')
//cout << svec[i] << endl;
svec[i] = "laaaaaaaaaaaaaaaaa";
}
else {
if ((i+1) != svec.size() && svec[i+1][0] == 'd')
//cout << svec[i] << endl;
svec[i] = "laaaaaaaaaaaaaaaaa";
}
}
for (auto i : svec)
{
if (i != "laaaaaaaaaaaaaaaaa")
news.push_back(i);
}
//for (auto i : svec)
// output << i << endl;
for (int i = 0; i <= news.size(); ++i)
{
if (i + 1 == news.size()) break;
string str = news[i] + ' ' + news[i + 1];
//string str = news[i+1] + ' ' + news[i];
++i;
if (i == news.size()) break;
int a = stoi(str.substr(13,3)) + 1;
output << str.substr(2,10);
output << setw(3) << setfill('0')<< a << ' '
<< "./bedroom_0014/" << i/2 + 1 << "_depth.png" << ' '
<< "./bedroom_0014/" << i/2 + 1 << "_rgb.ppm" << ' '
<< str << endl;
}
return 0;
}
修改图片名字的代码
彩色图使用UNCHANGED的,输入两个地址,第一个原始图像文件夹,第二个是目标文件夹
深度图imread参数取值1,后缀为_depth.png
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <iomanip>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
// 改图片名字
int main(int argc, char** argv) {
if (argc != 3) {
cout << "srcPath targetPath" << endl;
return 1;
}
String srcPath = string(argv[1]);
String targetPath = string(argv[2]);
vector<String> names;
glob(srcPath, names, false);
int size = names.size();
if (size == 0)
{
cout << "empty files" << endl;
return 1;
}
else {
for (int i = 0; i < size; ++i) {
Mat m = imread(names[i], CV_LOAD_IMAGE_UNCHANGED);
stringstream ss;
ss << i + 1 << "_rgb.ppm";
string newName = ss.str();
imwrite(targetPath + "/" + newName, m);
}
}
return 0;
}
bedroom14数据集效果