室内场景重建三 点面分割

简介

上篇博客室内场景重建二 立方体拟合中, 介绍了如何在粗略平面估计的基础上, 做精细化的处理, 最终得到了室内场景的6个非常精细的平面估计, 以及这个场景的一些测绘数据.

本篇将在上篇的结果的基础上, 将原始的panasonic_0.1_n.ply中的点分成三类:

  • 室外的点, 即噪点
  • 在室内, 且在平面上的点, 即在6个墙面上的点
  • 在室内, 但不在平面上的点, 即室内人和物的点.

实现思路

分割噪点

理论思路

已知由6个平面确定的立方体 V = [ P b u t t o n , P t o p , P b a c k , P f r o n t , P l e f t , P r i g h t ] , P i = [ A i , B i , C i , − 1 ] V=[P_{button}, P_{top}, P_{back}, P_{front}, P_{left}, P_{right}], P_i =[A_i, B_i, C_i, -1] V=[Pbutton,Ptop,Pback,Pfront,Pleft,Pright],Pi=[Ai,Bi,Ci,1], 且已知这个立方体的长宽高为 l e n g t h , w i d t h , h e i g h t length, width, height length,width,height, 已知点 P o i n t = [ x , y , z ] Point=[x, y, z] Point=[x,y,z], 可以求得如下的六个距离:
d i s b u t t o n = d i s t a n c e _ p o i n t _ t o _ p l a n e ( P o i n t , P l a n e b u t t o n ) d i s t o p = d i s t a n c e _ p o i n t _ t o _ p l a n e ( P o i n t , P l a n e t o p ) d i s b a c k = d i s t a n c e _ p o i n t _ t o _ p l a n e ( P o i n t , P l a n e b a c k ) d i s f r o n t = d i s t a n c e _ p o i n t _ t o _ p l a n e ( P o i n t , P l a n e f r o n t ) d i s l e f t = d i s t a n c e _ p o i n t _ t o _ p l a n e ( P o i n t , P l a n e l e f t ) d i s r i g h t = d i s t a n c e _ p o i n t _ t o _ p l a n e ( P o i n t , P l a n e r i g h t ) dis_{button} = distance\_point\_to\_plane(Point, Plane_{button}) \\ dis_{top} = distance\_point\_to\_plane(Point, Plane_{top}) \\ dis_{back} = distance\_point\_to\_plane(Point, Plane_{back}) \\ dis_{front} = distance\_point\_to\_plane(Point, Plane_{front}) \\ dis_{left} = distance\_point\_to\_plane(Point, Plane_{left}) \\ dis_{right} = distance\_point\_to\_plane(Point, Plane_{right}) \\ disbutton=distance_point_to_plane(Point,Planebutton)distop=distance_point_to_plane(Point,Planetop)disback=distance_point_to_plane(Point,Planeback)disfront=distance_point_to_plane(Point,Planefront)disleft=distance_point_to_plane(Point,Planeleft)disright=distance_point_to_plane(Point,Planeright)
取:
d i s _ m a x 0 = m a x ( d i s b u t t o n , d i s t o p ) d i s _ m a x 1 = m a x ( d i s b a c k , d i s f r o n t ) d i s _ m a x 2 = m a x ( d i s l e f t , d i s r i g h t ) dis\_max_0 = max(dis_{button}, dis_{top}) \\ dis\_max_1 = max(dis_{back}, dis_{front}) \\ dis\_max_2 = max(dis_{left}, dis_{right}) \\ dis_max0=max(disbutton,distop)dis_max1=max(disback,disfront)dis_max2=max(disleft,disright)
那么, 只要这个点在室外, 下面的语句_值必为True:
( d i s _ m a x 0 > h e i g h t )   ∣ ∣   ( d i s _ m a x 1 > w i d t h )   ∣ ∣   ( d i s _ m a x 2 > l e n g t h ) (dis\_max_0>height) \ || \ (dis\_max_1>width) \ || \ (dis\_max_2>length) (dis_max0>height)  (dis_max1>width)  (dis_max2>length)
考虑到一些误差, 这里可以加上一个阈值, 变成:
( d i s _ m a x 0 > h e i g h t + ϵ )   ∣ ∣   ( d i s _ m a x 1 > w i d t h + ϵ )   ∣ ∣   ( d i s _ m a x 2 > l e n g t h + ϵ ) (dis\_max_0>height+\epsilon) \ || \ (dis\_max_1>width+\epsilon) \ || \ (dis\_max_2>length+\epsilon) (dis_max0>height+ϵ)  (dis_max1>width+ϵ)  (dis_max2>length+ϵ)

编程实现

def sample_condition_points_outside_planes(points, planes, cube):
    """
    从points中, 挑选出在立方体外面的点, 返回一个sample_condition
    根据点到对应两个面的距离来判断, 如果有一个距离大于立方体的一个长度度量, 则认为这个点在立方体外面
    @param points:
    @param planes:      [下, 上, 后, 前, 左, 右]  0,1  2,3  4,5
    @param cube:        [高度, 宽度, 长度]        0,   1,   2
    @return:            np.ndarray, dtype=bool
    """
    if not type(points) == np.array:
        points = np.array(points)

    if not type(planes) == np.array:
        planes = np.array(planes)

    if not type(cube) == np.array:
        cube = np.array(cube)

    sample_condition = np.zeros(shape=(points.shape[0],), dtype=np.bool)  # 假设所有的点都在立方体内
    for i, point in enumerate(points):
        for j in range(cube.shape[0]):
            plane_1, plane_2 = planes[2 * j], planes[2 * j + 1]
            length = cube[j]
            dis_1 = distance_point_to_plane(point, plane_1)
            dis_2 = distance_point_to_plane(point, plane_2)
            # 该点某个坐标不在立方体内, 跳过剩余判断
            if (dis_1 > length+2*POINT_PLANE_DIS_THRESHOLD) or (dis_2 > length+2*POINT_PLANE_DIS_THRESHOLD):
                sample_condition[i] = True

    return sample_condition

分割室内点

理论思路

去掉了上面的点, 那么剩下来的点就都是室内的点了, 而具体分割这个点属于某个墙面, 还是属于某个物体, 采用的方法依然是基于点到直线的距离的.

依然取上面介绍的6个距离 d i s b u t t o n , d i s t o p , d i s b a c k , d i s f r o n t , d i s l e f t , d i s r i g h t dis_{button}, dis_{top}, dis_{back}, dis_{front}, dis_{left}, dis_{right} disbutton,distop,disback,disfront,disleft,disright, 只要某个 d i s < ϵ dis<\epsilon dis<ϵ, 则认为这个点在这个平面上

那么去除在平面上的点, 剩下来的就是既不在室外, 也不在平面上的点, 也就是室内人和物的点.

编程实现

def sample_condition_points_off_planes(points, planes):
    """
    从points中, 挑选出离planes特别远的点, 返回一个sample_condition
    @param points:
    @param planes:
    @return:            np.ndarray
    """
    if not type(points) == np.array:
        points = np.array(points)

    if not type(planes) == np.array:
        planes = np.array(planes)

    sample_condition = np.ones(shape=(points.shape[0],), dtype=np.bool)  # 假设所有点都不在平面上
    for idx, point in enumerate(points):
        for plane in planes:
            dis = distance_point_to_plane(point, plane)
            if dis < POINT_PLANE_DIS_THRESHOLD:  # 该点在某一平面上, 跳过判断剩余的平面
                sample_condition[idx] = False
                break

    return sample_condition

结果

将分割结果写入.objmtl后, 显示如下图:

在这里插入图片描述

其中从左到右, 从上到下分别是室内人和物的点, 6个墙面上的点, 室外噪点, 6个墙面

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

对象被抛出

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值