PCL实现RGB-D遇到的问题(记录)

接着上一次的AR传送门,给老师看了之后,又给了后面的任务:

上一个项目里面是虚拟的box(我放了水面的贴图和小球)现在给了通过kinect获得的RGB图像和深度图像,利用这两个三维重建一下,kinect是保持不动的,当然这样重建肯定会因为有一些角度拍不到导致一些地方像素缺失,但是上一个AR项目里也能看到,AR只能看到box的一部分,通过移动进行观察的角度是有限的,所以将三维重建的模型拉远一点,这样就不会露馅了。

上次的demo

现阶段要做的东西,画画帮助理解一下。

PCL实现RGB-D遇到的问题(记录)_第1张图片

 PCL实现RGB-D遇到的问题(记录)_第2张图片

 

具体实现

需要解决以下的问题:

1.读取视频,并提取其中的每一帧

先暂时不管,我先从深度视频和彩色视频各提取第一帧画面来代替。

使用ScreenToGif以20帧播放,将帧图片全部提取出来,15秒左右的视频,深度视频和彩色视频各提取300多张。

2.将彩色图和深度图转换成点云(RGB-D),绘制Mesh

安装配置colmap搞了一天,试了一下感觉用它好像没法做出我想要的效果

生成点云的代码参考:一起做RGB-D SLAM (2)  https://www.cnblogs.com/gaoxiang12/p/4652478.html

因为我手头上没有kinect,拜托了在学校的学长拍了两组深度视频和彩色视频,利用这两个视频每一帧,RGB图+Depth深度图在PCL中生成点云数据。然后再到unity中,利用这些点云数据去绘制mesh。

想法是我先用opencv,将每一帧深度图像的深度值、行列坐标提取出来,做一个点云数据。到时候在unity中用这个点云数据去绘制mesh

PCL实现RGB-D遇到的问题(记录)_第3张图片PCL实现RGB-D遇到的问题(记录)_第4张图片

运行代码生成pcd文件后,将生成的xxx.pcd文件复制到pcl-xx\bin目录中,命令行执行(懒狗一只,在bin目录下面写个脚本,每次生成完点云,运行脚本自动复制过来并执行)

pcl_viewer.exe xxx.pcd

生成的点云效果还可以

PCL实现RGB-D遇到的问题(记录)_第5张图片

 问题来了,我没有相机的参数,怎么办,总不能一点一点试吧(试完所有的参数总能试出来),手边也没有kinect,没法标定。去网上找了一组kinect的内参凑合着用吧。

PCL实现RGB-D遇到的问题(记录)_第6张图片

 

后来我将两张图片都旋转180度,还专门让深度图镜像翻转了一次。

 

还是有问题:

后来的补充:我在解决问题3之后发现,问题1和2都能在解决3之后被解决。所以可以直接跳到3

1、这莫名其妙出现的两个平面

PCL实现RGB-D遇到的问题(记录)_第7张图片

PCL实现RGB-D遇到的问题(记录)_第8张图片

怀疑是和图像位数有关,示例的图片深度图是16位,RGB图是32位。我用的RGB图和深度图都是32位的。输出了一下像素的深度值,示例的深度值在0~2000,而示例的缩放因子s的值为1000,我的在4000~65300。发现4000和65535之间跨度特别大而且中间几乎没有其他的值,于是在生成点云时,将深度值大于60000的点剔除,发现一个平面成功处理掉了。(剔除之后点云的数量变为了原来的一半)

PCL实现RGB-D遇到的问题(记录)_第9张图片

另一个平面,估计是因为和深度图不能对齐的原因。

2、开始的时候图像是颠倒的。虽然已经大致可以看出深度的轮廓了,但是这个深度图是反着的,即该凹的地方凸,该凸的地方凹。

解决办法:在相机缩放因子camera_factor上添加一个负号就行了。

PCL实现RGB-D遇到的问题(记录)_第10张图片

这个其实也没什么,我参考的博客的示例,在pcl_viewer.exe上显示也是颠倒的。可能是pcl_viewer预定义的坐标轴方向有关

PCL实现RGB-D遇到的问题(记录)_第11张图片 原图 PCL实现RGB-D遇到的问题(记录)_第12张图片 pcl_viewer显示的点云

3、点云凹凸的部分和彩色图像没有对齐的,有一定的偏移

左边的红圈应该对应右边红圈的位置,结果出现了偏移

PCL实现RGB-D遇到的问题(记录)_第13张图片

更奇怪的是,如果我将图片旋转180度,生成的点云是可以明显看到整个人的形状的,虽然还是有偏移

PCL实现RGB-D遇到的问题(记录)_第14张图片

 而且深度图人物的头有彩色图里两个那么大?我开始怀疑是深度图读取时候出了什么问题。

PCL实现RGB-D遇到的问题(记录)_第15张图片

我使用的代码中,读取深度值存储的变量类型是ushort,而示例的深度图是16位的。我的深度图像是32位的,于是将ushort改成int,解决了问题。不仅如此,连问题1中多出来的平面都没有了,图像也没有问题2中的上下颠倒,变成了pcl_viewer中显示的点云好像与原图镜面翻转了。 

但现在又发现了一个新问题,虽然整个人的轮廓已经凸出来了,但是杯子应该是在胳膊前面的,而杯子却相比于胳膊凹陷下去了。

PCL实现RGB-D遇到的问题(记录)_第16张图片

PCL实现RGB-D遇到的问题(记录)_第17张图片

PCL实现RGB-D遇到的问题(记录)_第18张图片

输出一下图像的通道数:

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模板T的类型是Vec4b,下图来自https://blog.csdn.net/leonardohaig/article/details/81587421

PCL实现RGB-D遇到的问题(记录)_第19张图片

注意:Opencv中颜色通道的顺序是BGR而不是RGB

Mat的at是行列。即at(r,c)对应at(y,x)

检查了一下,所有像素点的alpha值都是255,不需要关心。采用平均值法来将BGR三个值转换成一个值。

这是读取了正常的深度值,正常的bgr值之后生成的点云图。

PCL实现RGB-D遇到的问题(记录)_第20张图片

 给点云的y加了个负号将方向正过来。问题依然存在,并不是因为读取的原因,而是深度图的问题。

我沿蓝线从上到下输出了一下的各个像素点的RGB+D值,格式为:[RGB图](B,G,R)[深度图](B,G,R)[深度图]计算的平均深度值,观察输出的值能够发现,深度值的关系是:衣服处>胳膊处>黑色部分。这也就是为什么我生成的点云里,胳膊部分会凹下去。

PCL实现RGB-D遇到的问题(记录)_第21张图片

(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.深度图和彩色图没有对齐

调整一下透明度,可以看到有一定的偏移。不过这已经算小瑕疵了,日后留着和滤波一起再处理。

PCL实现RGB-D遇到的问题(记录)_第22张图片

 

3.绘制出的Mesh如何与RGB图对应起来

4.从侧面看的时候,如何才能不突兀

 

 

 

 

 

总结

=

你可能感兴趣的:(PCL)