接着上一次的AR传送门,给老师看了之后,又给了后面的任务:
上一个项目里面是虚拟的box(我放了水面的贴图和小球)现在给了通过kinect获得的RGB图像和深度图像,利用这两个三维重建一下,kinect是保持不动的,当然这样重建肯定会因为有一些角度拍不到导致一些地方像素缺失,但是上一个AR项目里也能看到,AR只能看到box的一部分,通过移动进行观察的角度是有限的,所以将三维重建的模型拉远一点,这样就不会露馅了。
上次的demo现阶段要做的东西,画画帮助理解一下。
需要解决以下的问题:
先暂时不管,我先从深度视频和彩色视频各提取第一帧画面来代替。
使用ScreenToGif以20帧播放,将帧图片全部提取出来,15秒左右的视频,深度视频和彩色视频各提取300多张。
安装配置colmap搞了一天,试了一下感觉用它好像没法做出我想要的效果
生成点云的代码参考:一起做RGB-D SLAM (2) https://www.cnblogs.com/gaoxiang12/p/4652478.html
因为我手头上没有kinect,拜托了在学校的学长拍了两组深度视频和彩色视频,利用这两个视频每一帧,RGB图+Depth深度图在PCL中生成点云数据。然后再到unity中,利用这些点云数据去绘制mesh。
想法是我先用opencv,将每一帧深度图像的深度值、行列坐标提取出来,做一个点云数据。到时候在unity中用这个点云数据去绘制mesh
运行代码生成pcd文件后,将生成的xxx.pcd文件复制到pcl-xx\bin目录中,命令行执行(懒狗一只,在bin目录下面写个脚本,每次生成完点云,运行脚本自动复制过来并执行)
pcl_viewer.exe xxx.pcd
生成的点云效果还可以
问题来了,我没有相机的参数,怎么办,总不能一点一点试吧(试完所有的参数总能试出来),手边也没有kinect,没法标定。去网上找了一组kinect的内参凑合着用吧。
后来我将两张图片都旋转180度,还专门让深度图镜像翻转了一次。
还是有问题:
后来的补充:我在解决问题3之后发现,问题1和2都能在解决3之后被解决。所以可以直接跳到3
1、这莫名其妙出现的两个平面
怀疑是和图像位数有关,示例的图片深度图是16位,RGB图是32位。我用的RGB图和深度图都是32位的。输出了一下像素的深度值,示例的深度值在0~2000,而示例的缩放因子s的值为1000,我的在4000~65300。发现4000和65535之间跨度特别大而且中间几乎没有其他的值,于是在生成点云时,将深度值大于60000的点剔除,发现一个平面成功处理掉了。(剔除之后点云的数量变为了原来的一半)
另一个平面,估计是因为和深度图不能对齐的原因。
2、开始的时候图像是颠倒的。虽然已经大致可以看出深度的轮廓了,但是这个深度图是反着的,即该凹的地方凸,该凸的地方凹。
解决办法:在相机缩放因子camera_factor上添加一个负号就行了。
这个其实也没什么,我参考的博客的示例,在pcl_viewer.exe上显示也是颠倒的。可能是pcl_viewer预定义的坐标轴方向有关
原图 pcl_viewer显示的点云3、点云凹凸的部分和彩色图像没有对齐的,有一定的偏移
左边的红圈应该对应右边红圈的位置,结果出现了偏移
更奇怪的是,如果我将图片旋转180度,生成的点云是可以明显看到整个人的形状的,虽然还是有偏移
而且深度图人物的头有彩色图里两个那么大?我开始怀疑是深度图读取时候出了什么问题。
我使用的代码中,读取深度值存储的变量类型是ushort,而示例的深度图是16位的。我的深度图像是32位的,于是将ushort改成int,解决了问题。不仅如此,连问题1中多出来的平面都没有了,图像也没有问题2中的上下颠倒,变成了pcl_viewer中显示的点云好像与原图镜面翻转了。
但现在又发现了一个新问题,虽然整个人的轮廓已经凸出来了,但是杯子应该是在胳膊前面的,而杯子却相比于胳膊凹陷下去了。
输出一下图像的通道数:
Mat img = imread(xxx);
示例图像:RGB:3通道;D图:1通道。
我的图像:RGB:3通道;D图:4通道。
可能是因为这图像是从视频里截取出来的,有RGBA共4个通道。使用cout输出一下深度图depth。发现确实是每个像素点有4个值组成。大部分黑色的位置是(16,16,16,255)对应(R,G,B,A),现在问题在于我使用ptr和at都无法提取出RGB的int值。
使用depth.type()来查看该Mat存储的元素类型(type),返回值为24,查表(参考https://blog.csdn.net/pekingFloater/article/details/82688327)对应CV_8UC4。
继续查对应Mat at
注意:Opencv中颜色通道的顺序是BGR而不是RGB
Mat的at是行列。即at(r,c)对应at(y,x)
检查了一下,所有像素点的alpha值都是255,不需要关心。采用平均值法来将BGR三个值转换成一个值。
这是读取了正常的深度值,正常的bgr值之后生成的点云图。
给点云的y加了个负号将方向正过来。问题依然存在,并不是因为读取的原因,而是深度图的问题。
我沿蓝线从上到下输出了一下的各个像素点的RGB+D值,格式为:[RGB图](B,G,R),[深度图](B,G,R),[深度图]计算的平均深度值,观察输出的值能够发现,深度值的关系是:衣服处>胳膊处>黑色部分。这也就是为什么我生成的点云里,胳膊部分会凹下去。
(49,54,52),(16,16,16),16
(52,57,55),(16,16,16),16
(56,61,59),(16,16,16),16
(61,66,64),(16,16,16),16
(66,71,69),(16,16,16),16
(83,88,86),(16,16,16),16
(101,106,104),(15,15,15),15
(103,108,106),(16,16,16),16
(106,111,109),(16,16,16),16
(72,77,75),(16,16,16),16
(38,43,41),(15,15,15),15
(36,41,39),(16,16,16),16
(34,39,37),(16,16,16),16
(32,37,35),(16,16,16),16
(30,35,33),(16,16,16),16
(33,38,36),(16,16,16),16
(37,42,40),(16,16,16),16
(37,42,40),(16,16,16),16
(37,42,40),(16,16,16),16
(36,41,39),(16,16,16),16
(36,41,39),(16,16,16),16
(35,40,38),(16,16,16),16
(35,40,38),(16,16,16),16
(34,39,37),(16,16,16),16
(34,39,37),(16,16,16),16
(33,38,36),(16,16,16),16
(33,38,36),(16,16,16),16
(33,38,36),(16,16,16),16
(33,38,36),(16,16,16),16
(32,37,35),(16,16,16),16
(32,37,35),(15,17,15),15
(32,37,35),(15,17,15),15
(32,37,35),(15,17,15),15
(31,36,35),(15,17,15),15
(31,36,35),(15,17,15),15
(31,36,35),(15,17,15),15
(31,36,35),(15,17,15),15
(31,36,35),(15,17,15),15
(31,36,35),(15,17,15),15
(31,36,35),(15,17,15),15
(31,36,35),(16,18,16),16
(31,36,35),(15,17,15),15
(30,36,35),(14,16,14),14
(30,36,35),(15,17,15),15
(30,36,35),(15,17,15),15
(29,36,35),(16,18,16),16
(28,36,35),(16,19,17),17
(28,36,35),(17,20,18),18
(28,36,36),(18,21,19),19
(28,36,37),(18,21,19),19
(28,36,38),(18,21,19),19
(28,36,39),(34,37,35),35
(28,36,39),(50,53,51),51
(27,36,40),(51,54,52),52
(26,36,40),(53,56,54),54
(27,38,42),(53,56,54),54
(29,40,45),(53,56,54),54
(47,58,65),(52,55,53),53
(66,78,85),(52,55,53),53
(95,108,116),(51,54,52),52
(124,138,147),(51,54,52),52
(121,136,145),(50,53,51),51
(120,135,145),(50,53,51),51
(115,130,142),(50,53,51),51
(111,126,138),(50,53,51),51
(107,123,136),(50,53,51),51
(103,120,134),(50,53,51),51
(99,115,131),(50,53,51),51
(96,112,128),(50,53,51),51
(94,110,127),(50,53,51),51
(91,108,125),(50,53,51),51
(88,106,123),(50,53,51),51
(86,103,122),(50,53,51),51
(85,103,122),(50,53,51),51
(85,103,122),(50,53,51),51
(84,104,122),(50,53,51),51
(84,104,122),(50,53,51),51
(83,103,121),(50,53,51),51
(83,103,121),(50,53,51),51
(82,102,120),(50,53,51),51
(81,101,119),(50,53,51),51
(80,100,118),(50,53,51),51
(79,99,117),(50,53,51),51
(78,98,116),(50,53,51),51
(78,98,116),(50,53,51),51
(78,98,116),(50,53,51),51
(78,98,116),(50,53,51),51
(78,98,115),(50,53,51),51
(78,98,115),(50,53,51),51
(78,98,115),(50,53,51),51
(78,98,115),(50,53,51),51
(77,97,114),(50,53,51),51
(77,97,114),(50,53,51),51
(77,97,114),(50,53,51),51
(77,97,114),(50,53,51),51
(76,96,113),(50,53,51),51
(76,96,113),(50,53,51),51
(76,96,113),(50,53,51),51
(76,97,112),(50,53,51),51
(77,98,113),(50,53,51),51
(78,99,114),(50,53,51),51
(78,99,114),(50,53,51),51
(79,100,115),(50,53,51),51
(79,100,115),(50,53,51),51
(79,100,115),(50,53,51),51
(79,100,115),(50,53,51),51
(79,100,115),(50,53,51),51
(78,99,114),(50,53,51),51
(77,98,113),(50,53,51),51
(76,97,112),(50,53,51),51
(76,96,110),(50,53,51),51
(76,95,108),(50,53,51),51
(77,95,108),(51,54,52),52
(74,92,105),(51,54,52),52
(72,91,102),(51,54,52),52
(70,89,100),(51,54,52),52
(69,87,97),(51,54,52),52
(67,84,93),(54,57,55),55
(65,82,89),(57,60,58),58
(58,74,80),(62,65,63),63
(53,67,72),(66,69,67),67
(38,50,54),(66,69,67),67
(21,34,36),(67,70,68),68
(20,32,33),(67,70,68),68
(20,30,31),(68,71,69),69
(20,30,30),(68,71,69),69
(21,30,29),(68,71,69),69
(21,30,28),(68,71,69),69
(22,30,27),(68,71,69),69
(22,30,26),(68,71,69),69
(22,30,26),(68,71,69),69
(22,31,25),(68,71,69),69
(23,30,25),(68,71,69),69
(23,30,25),(68,71,69),69
(23,30,25),(68,71,69),69
(23,30,25),(68,71,69),69
(23,30,25),(68,71,69),69
(23,30,25),(68,71,69),69
(23,30,25),(68,71,69),69
(22,29,24),(68,71,69),69
(22,29,24),(68,71,69),69
(22,29,24),(68,71,69),69
(22,29,24),(68,71,69),69
(22,29,24),(68,71,69),69
(22,29,24),(69,71,69),69
(22,29,24),(68,70,68),68
(22,29,24),(68,70,68),68
(21,28,23),(68,70,68),68
(21,28,23),(69,71,69),69
(21,28,23),(69,71,69),69
(22,29,24),(69,71,69),69
(22,29,24),(69,71,69),69
(22,29,24),(69,71,69),69
(22,29,24),(69,71,69),69
(22,29,24),(69,71,69),69
(21,28,23),(69,71,69),69
(21,28,23),(69,71,69),69
(21,29,23),(69,71,69),69
(21,29,22),(69,71,69),69
(21,29,22),(68,70,68),68
(22,30,23),(68,70,68),68
(22,30,23),(67,69,67),67
(22,30,23),(67,69,67),67
(22,30,23),(67,69,67),67
(22,30,23),(67,69,67),67
(22,30,23),(66,68,66),66
(22,30,23),(66,68,66),66
(22,30,23),(65,67,65),65
(22,30,23),(65,67,65),65
(22,30,23),(64,66,64),64
(22,30,23),(64,66,64),64
(22,30,23),(64,66,64),64
(22,30,23),(64,66,64),64
(22,30,23),(64,66,64),64
(22,30,23),(64,66,64),64
(22,30,23),(63,65,63),63
(22,30,23),(63,65,63),63
(22,30,23),(63,65,63),63
(22,30,23),(63,65,63),63
(22,30,23),(63,65,63),63
(22,30,23),(63,65,63),63
(22,30,23),(63,65,63),63
(22,30,23),(64,66,64),64
(22,30,23),(65,67,65),65
(22,30,23),(66,68,66),66
(22,30,23),(66,68,66),66
(22,30,23),(67,69,67),67
(22,30,23),(68,70,68),68
(22,30,23),(69,71,69),69
(22,30,23),(69,71,69),69
(22,30,23),(69,71,69),69
(22,30,23),(69,71,69),69
(22,30,23),(69,71,69),69
(22,30,23),(68,70,68),68
(22,30,23),(68,70,68),68
(22,30,23),(68,70,68),68
(22,30,23),(68,70,68),68
(22,30,23),(68,70,68),68
(22,30,23),(68,70,68),68
(22,30,23),(68,70,68),68
(22,30,23),(69,71,69),69
(21,29,22),(69,71,69),69
(21,29,22),(69,71,69),69
(21,29,22),(69,71,69),69
(21,29,22),(69,71,69),69
(21,29,22),(68,70,68),68
(21,29,22),(68,70,68),68
(21,29,22),(66,68,66),66
(22,29,22),(64,66,64),64
(22,29,22),(41,43,41),41
(22,29,22),(19,21,19),19
(22,29,22),(16,18,16),16
(22,29,22),(14,16,14),14
(25,32,25),(15,17,15),15
(28,35,28),(15,17,15),15
(46,53,46),(15,17,15),15
(65,72,65),(14,16,14),14
(69,76,69),(14,16,14),14
(74,81,74),(14,16,14),14
(65,72,65),(16,18,16),16
(56,63,56),(19,21,19),19
(56,63,56),(42,44,42),42
(56,63,56),(65,67,65),65
(57,63,56),(63,65,63),63
(58,63,56),(62,64,62),62
(57,61,55),(61,63,61),61
(57,61,55),(61,63,61),61
(56,60,54),(39,41,39),39
(56,60,54),(17,19,17),17
(60,64,58),(15,17,15),15
(64,68,62),(14,16,14),14
(71,75,69),(15,17,15),15
(78,82,76),(15,17,15),15
(83,87,81),(15,17,15),15
(88,92,86),(15,17,15),15
(82,86,80),(15,17,15),15
(77,81,75),(15,17,15),15
(74,78,72),(15,17,15),15
(71,75,69),(15,17,15),15
贴一下生成点云的代码:
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef pcl::PointXYZRGBA PointT;
typedef pcl::PointCloud PointCloud;
// 相机内参
/*
//示例图片的相机参数
const double camera_factor = 1000;
const double camera_cx = 325.5;
const double camera_cy = 253.5;
const double camera_fx = 518.0;
const double camera_fy = 519.0;
*/
//kinect相机参数
const double camera_factor = 1;//缩放因子
const double camera_cx = 400;
const double camera_cy = 209.32;
const double camera_fx = 364.032;
const double camera_fy = 364.032;
/**/
int generatepcd()
{
cv::Mat rgb, depth;
rgb = cv::imread("./data/RGB.png");
depth = cv::imread("./data/depth.png", -1);
//输出元素的类型
//cout << rgb.type() << endl;
//cout << depth.type() << endl;
//示例图片
//rgb = cv::imread("./data/rgb1.png");
//depth = cv::imread("./data/d.png", -1);
//cout << "RGB通道数:" << rgb.channels() << endl;
//cout << "D通道数:" << depth.channels() << endl;
//cv::imshow("rgb", rgb);
//cv::imshow("depth", depth);
//cv::waitKey(0);
// 点云
PointCloud::Ptr cloud(new PointCloud);
/*
//输出D图的4个通道的值
cout << depth.at(2,2) << endl;
//输出RGB图的3个通道的值
cout << rgb.at(2, 2) << endl;
*/
// 遍历深度图
for (int m = 0; m < depth.rows; m++) {
for (int n = 0; n < depth.cols; n++)
{
// 获取深度图中(m,n)处的值
//ushort d = depth.ptr(m)[n];
int d = depth.ptr(m)[n];
//采用平均值来获得深度值
int B = (int)depth.at(m, n)[0];
int G = (int)depth.at(m, n)[1];
int R = (int)depth.at(m, n)[2];
d = (B + G + R) / 3;
PointT p;
// 计算这个点的空间坐标
p.z = double(d) / camera_factor;
p.x = (n - camera_cx) * p.z / camera_fx;
p.y = -(m - camera_cy) * p.z / camera_fy;
//cout << p.z << endl;
// 从rgb图像中获取它的颜色
// rgb是三通道的BGR格式图,所以按下面的顺序获取颜色
p.b = (int)rgb.at(m,n)[0];
p.g = (int)rgb.at(m,n)[1];
p.r = (int)rgb.at(m, n)[2];
//if (n == depth.cols / 2 && m > depth.rows / 2)
// printf("(%d,%d,%d),(%d,%d,%d),%d\n", p.b, p.g, p.r,B,G,R,d);
// 把p加入到点云中
cloud->points.push_back(p);
}
}
// 设置并保存点云
cloud->height = 1;
cloud->width = cloud->points.size();
cout << "point cloud size = " << cloud->points.size() << endl;
cloud->is_dense = false;
pcl::io::savePCDFile("./pointcloud.pcd", *cloud);
// 清除数据并退出
cloud->points.clear();
cout << "Point cloud saved." << endl;
cin.get();
return 0;
}
int main(int argc, char** argv) {
generatepcd();
}
4.深度图和彩色图没有对齐
调整一下透明度,可以看到有一定的偏移。不过这已经算小瑕疵了,日后留着和滤波一起再处理。
=