论文复现-一种基于室内点云数据的建筑墙线提取

研究意义

针对室内点云数据无结构化属性、数据间无连接、不承载语义信息且数据点密度高的特点,结合建筑物点云几何特征室内导航需求,通过数据降维简化建筑几何特征提取的复杂性,提出一种基于室内点云数据提取建筑物墙线的方法

算法思路

  • 首先通过向特定方向投影,利用点云密度直方图完成天花板面、地板面和房间墙面的初步分割;
  • 然后将房间墙面点云数据向地面投影,生成点云分布矩阵并将其转化为二值图,利用Hough变换算法提取直线,并利用直线方程求取交点得到备选墙线;
  • 最后将备选墙线和墙线点云二值图进行叠加从而获取最终建筑墙线。

实验步骤

编程语言?不要纠结,认清一点,编程语言只是工具,重要的的算法的逻辑思路,什么语言方便用什么语言。matlab虽然算法编程简单,矩阵运算方便,但是再人工编写的循环中不如C++Eigen。

本人编程语言:

  • matlab:主要负责显示图像和简单运算
  • C++:主要负责算法实现Eigen。

分割出墙

1、使用matlab尝试向坐标轴投影生成点云密度直方图。

  • 代码
clc,clear
%%%将点云向坐标轴z投影生成点云密度直方图。
home=importdata('hallway_2.txt');%读取txt点云数据
home_z=home(:,3);%获取点云z轴数据,即向z轴投影
h=histogram(home_z);%显示密度直方图
h.BinWidth=0.02;%设置尺度后再画图,也可以默认

% 总结:
% hallway_2.txt 提取墙面范围[0.02,2.56]
% 
  • 实验结果
    在这里插入图片描述

2、使用C++对点云直通滤波,提取墙的那部分:

  • 关键代码
	pcl::PassThrough<pcl::PointXYZ> pass;// 创建滤波器对象
	pass.setInputCloud(cloud);
	pass.setFilterFieldName("z"); //滤波字段名被设置为Z轴方向
	pass.setFilterLimits(0.02, 2.56); //设置在过滤方向上的过滤范围
	pass.setNegative(false); //设置保留范围内的还是过滤掉范围内的,标志为false时保留范围内的点
	pass.filter(*cloud_filtered);
  • 实验结果
    在这里插入图片描述

霍夫变换找线

1、墙点云向地面投影最终生成二值图
//获取点云中的最值数据
最小值:x_min=-13.084 y_min=4.321 z_min=0.02
最大值:x_max=-6.018 y_max=5.956 z_max=2.56
//设置像素为0.02m计算矩阵的行列数
矩阵大小:91x363
//开始投影,计算每个像素内的点云数,生成点云分布矩阵

  • 代码
	cout << "/*---------------------------------------------------------------*/" << endl;
	cout << "/*开始向地面投影生成点云分布矩阵*/" << endl;
	//获取点云中的最值数据
	PointT minPt, maxPt;//把最大/最小用点来存
	pcl::getMinMax3D(*cloud, minPt, maxPt);
	cout << "最小值:x_min=" << minPt.x << " y_min=" << minPt.y << " z_min=" << minPt.z << endl;
	cout << "最大值:x_max=" << maxPt.x << " y_max=" << maxPt.y << " z_max=" << maxPt.z << endl;
	//设置像素为0.02m计算矩阵的行列数
	float pix_size = 0.02;
	int row = (maxPt.y+0.1 - (minPt.y-0.1)) / pix_size;//获得行数 宽松1dm
	int col = (maxPt.x + 0.1 - (minPt.x - 0.1)) / pix_size;//获得列数 宽松1dm
	cout << "矩阵大小:" << row << "x" << col << endl;
	//开始投影,计算每个像素内的点云数,生成点云分布矩阵
	Eigen::MatrixXf ground_matrix=Eigen::MatrixXf::Zero(row, col);//创建矩阵
	int row_n;//行下标
	int col_n;//列下标
	for (int i = 0; i < cloud->size(); i++)//遍历所有点,统计每个像素的点云数
	{
		//仅仅统计当前点x,y在哪个像素
		row_n = (cloud->points[i].y - (minPt.y - 0.1)) / pix_size;
		col_n = (cloud->points[i].x - (minPt.x - 0.1)) / pix_size;
		//对应像素+1
		ground_matrix(row_n, col_n) += 1;
	}
	//点云分布矩阵灰度化
	ground_matrix = 255 * ground_matrix / ground_matrix.maxCoeff();
	//灰度矩阵二值化
	float bin_threshold = 10;
	for (int i = 0; i < ground_matrix.rows(); i++)
	{
		for (int j = 0; j < ground_matrix.cols(); j++)
		{
			if (ground_matrix(i, j) > bin_threshold)	ground_matrix(i, j) = 1;
			else										ground_matrix(i, j) = 0;
		}
	}
	//将矩阵写入ground_matrix.txt
	ofstream outfile;
	outfile.open("ground_matrix.txt",ios::app);
	outfile << ground_matrix << endl;
	outfile.close();
	cout << "成功将矩阵写入文件" << endl;
  • 实验结果
    转为灰度图:
    在这里插入图片描述

转为二值图:
在这里插入图片描述
2、二值图进行霍夫变换找到备选墙线

  • matlab代码
BW  = importdata('ground_matrix_bin.txt');
[H,T,R] = hough(BW);%霍夫变换 H:霍夫矩阵,计票箱 T:theta R:rho
imshow(H,[],'XData',T,'YData',R,...
            'InitialMagnification','fit');%显示霍夫矩阵
xlabel('\theta'), ylabel('\rho');
axis on, axis normal, hold on;
P  = houghpeaks(H,10,'threshold',ceil(0.1*max(H(:))));%统计霍夫矩阵峰值 最大峰值数 阈值
x = T(P(:,2)); y = R(P(:,1));
plot(x,y,'s','color','white');%显示找到的峰值
% Find lines and plot them
lines = houghlines(BW,T,R,P,'FillGap',10,'MinLength',5);%遍历所有点的(tho,theta)找到所有的线段 FillGap:合并间距 MinLength:最短长度
figure, imshow(BW), hold on
max_len = 0;
for k = 1:length(lines)
   xy = [lines(k).point1; lines(k).point2];
   plot(xy(:,1),xy(:,2),'LineWidth',2,'Color','green');

   % Plot beginnings and ends of lines
   plot(xy(1,1),xy(1,2),'x','LineWidth',2,'Color','yellow');
   plot(xy(2,1),xy(2,2),'x','LineWidth',2,'Color','red');

   % Determine the endpoints of the longest line segment
   len = norm(lines(k).point1 - lines(k).point2);
   if ( len > max_len)%获得最大长度 对应端点
      max_len = len;
      xy_long = xy;
   end
end

% highlight the longest line segment
plot(xy_long(:,1),xy_long(:,2),'LineWidth',2,'Color','blue');
  • 实验结果
    标记的峰值
    在这里插入图片描述
    粗略地墙线,懒得写程序画直线了,画直线更简单,直接根据(rho,theta)的峰值,就确定了每条直线。
    在这里插入图片描述

叠加最终墙线

就是把二值图和备选墙线叠加,比较出来最终墙线。

总结与展望

  • 1
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值