pointcloud_homework4

task
Use KITTI 3D object detection dataset, do the followings.
Step 1. Remove the ground from the lidar points. Visualize ground as blue.
• Any method you want – LSQ, Hough, RANSAC
Step 2. Clustering over the remaining points. Visualize the clusters with random colors.
• Any method you want

solution

在jupyter notebook上完成并运行

1.读取KITTI的一个点云数据集并可视化


import open3d
import os
import struct
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
def read_velodyne_bin(path):
    '''
    :param path:
    :return: homography matrix of the point cloud, N*3
    '''
    pc_list = []
    with open(path, 'rb') as f:
        content = f.read()
        pc_iter = struct.iter_unpack('ffff', content)
        for idx, point in enumerate(pc_iter):
            pc_list.append([point[0], point[1], point[2]])
    return np.asarray(pc_list, dtype=np.float32)

path='D:\\lesson2code\\000000.bin'
#应替换为自己的数据路径
origindata=read_velodyne_bin(path)

pcd = open3d.geometry.PointCloud()

pcd.points = open3d.utility.Vector3dVector(origindata)
open3d.visualization.draw_geometries([pcd])

在这里插入图片描述

2.将点云地面的点提取并标记为蓝色

假设地面为水平,使用LeastSquare与RANSAC进行平面拟合,并取出平面附近的点作为地面

(1)最小二乘法函数


import numpy as np
import random

def PlaneLeastSquare(X:np.ndarray):
    #z=ax+by+c,return a,b,c
    A=X.copy()
    b=np.expand_dims(X[:,2],axis=1)
    A[:,2]=1
    
    #通过X=(AT*A)-1*AT*b直接求解

    A_T = A.T
    A1 = np.dot(A_T,A)
    A2 = np.linalg.inv(A1)
    A3 = np.dot(A2,A_T)
    x= np.dot(A3, b)
    return x

(2)RANSAC函数实现


import numpy as np
import random
import math
import sys

def PlaneRANSAC(X:np.ndarray,tao:float,e=0.4,N_regular=100):
    #return plane ids
    s=X.shape[0]
    
    count=0
    p=0.99
    dic={}
    
    #确定迭代次数
    if math.log(1-(1-e)**s)<sys.float_info.min:
        N=N_regular
    else:
        N=math.log(1-p)/math.log(1-(1-e)**s)
        
    #开始迭代
    while count < N:
        
        
        ids=random.sample(range(0,s),3)
        Points=X[ids]
        p1,p2,p3=X[ids]
        #判断是否共线
        L=p1-p2
        R=p2-p3
        if 0 in L or 0 in R:
            continue
        else:
            if L[0]/R[0]==L[1]/R[1]==L[2]/R[2]:
                continue
                
        #计算平面参数
        a = (p2[1] - p1[1])*(p3[2] - p1[2]) - (p2[2] - p1[2])*(p3[1] - p1[1]);     
        b = (p2[2] - p1[2])*(p3[0] - p1[0]) - (p2[0] - p1[0])*(p3[2] - p1[2]);     
        c = (p2[0] - p1[0])*(p3[1] - p1[1]) - (p2[1] - p1[1])*(p3[0] - p1[0]);     
        d = 0 - (a * p1[0] + b*p1[1] + c*p1[2]);
        
        dis=abs(a*X[:,0]+b*X[:,1]+c*X[:,2]+d)/(a**2+b**2+c**2)**0.5
        
        idset=[]
        for i ,d in enumerate(dis):
            if d <tao:
                idset.append(i)
        
        
        #再使用最小二乘法
        p=PlaneLeastSquare(X[idset])
        a,b,c,d=p[0],p[1],-1,p[2]
        
        
        dic[len(idset)]=[a,b,c,d]
        
        if len(idset)>s*(1-e):
            break
        
        count+=1
    
    parm=dic[max(dic.keys())]
    a,b,c,d=parm
    dis=abs(a*X[:,0]+b*X[:,1]+c*X[:,2]+d)/(a**2+b**2+c**2)**0.5
        
    idset=[]
    for i ,d in enumerate(dis):
        if d <tao:
            idset.append(i)
    return np.array(idset)

(3)调用并可视化



planeids=PlaneRANSAC(origindata,0.35)
planedata=origindata[planeids]
planepcd = open3d.geometry.PointCloud()
planepcd.points = open3d.utility.Vector3dVector(planedata)

c=[0,0,255]
cs=np.tile(c,(planedata.shape[0],1))
planepcd.colors=open3d.Vector3dVector(cs)

othersids=[]
for i in range(origindata.shape[0]):
    if i not in planeids:
        othersids.append(i)
otherdata=origindata[othersids]
otherpcd = open3d.geometry.PointCloud()
otherpcd.points = open3d.utility.Vector3dVector(otherdata)
c=[255,0,0]
cs=np.tile(c,(otherdata.shape[0],1))
otherpcd.colors=open3d.Vector3dVector(cs)
open3d.visualization.draw_geometries([planepcd,otherpcd])

在这里插入图片描述

3.对地面外的点云进行聚类

由于较难确定类别的数量,kmeans与GMM方法不太适用。现选用DBSCAN方法。

(1)自己的DBSCAN实现

代码的少部分片断借鉴于博客https://www.cnblogs.com/tiaozistudy/p/dbscan_algorithm.html.


import numpy as np
import random
from scipy.spatial import KDTree
import time
import sklearn.cluster #import DBSCAN

class visitlist:
    def __init__(self, count=0):
        self.unvisitedlist=[i for i in range(count)]
        self.visitedlist=list()
        self.unvisitednum=count

    def visit(self, pointId):
        self.visitedlist.append(pointId)
        self.unvisitedlist.remove(pointId)
        self.unvisitednum -= 1
        

        
class cluster:
    def __init__(self,ctype):
        self.ctypr=ctype
        self.points=list()
        
        
    
        
def DBSCAN(X:np.ndarray,r:float,minPts:int):
    pointnum=X.shape[0]
    v=visitlist(pointnum)
    clustersSet=list()
    noise=cluster(-1)
    tree=KDTree(X)
    k=0
    
    while v.unvisitednum>0:
        randid=random.choice(v.unvisitedlist)
        v.visit(randid)
        N = tree.query_ball_point(X[randid], r)
        if len(N)<minPts:            
            noise.points.append(randid)
        else:
            clus=cluster(k)
            clus.points.append(randid)
            N.remove(randid)
            while len(N)>0:
                p=N.pop()
                if p in v.unvisitedlist:
                    v.visit(p)
                    clus.points.append(p)
                    pN=tree.query_ball_point(X[p], r)
                    if len(pN)>=minPts:
                        pN.remove(p)
                        N=N+pN
            clustersSet.append(clus)
    
    clustersSet.append(noise)
    return clustersSet

测试自己的DBSCAN效果


import time
from sklearn import datasets
import matplotlib.pyplot as plt
centers = [[1, 1], [-1, -1], [-1, 1], [1, -1]]
pointlala, labelsTrue = datasets.make_blobs(n_samples=600, centers=centers, cluster_std=0.4,random_state=0)
C=DBSCAN(pointlala,0.3,10)


plt.scatter(pointlala[:,0],pointlala[:,1])
trys1=pointlala[C[0].points]
plt.scatter(trys1[:,0],trys1[:,1])
trys2=pointlala[C[1].points]
plt.scatter(trys2[:,0],trys2[:,1])
trys3=pointlala[C[2].points]
plt.scatter(trys3[:,0],trys3[:,1])
trys4=pointlala[C[3].points]
plt.scatter(trys4[:,0],trys4[:,1])

在这里插入图片描述

实践发现,自己实现的DBSCAN方法处理上述的点云数据耗时较久,预计完成聚类需要几个小时这样。最终还是放弃使用自己的DBSCAN方法对点云聚类,改用sklearn中的DBSCAN聚类方法。

(2)使用sklearn内的DBSCAN方法进行聚类

内心os:
原本打算每一个类用一种颜色,总共大概有七八十个类这样,但是发现运行时open3d可视化窗口一片空白(可能是电脑配置的缘故)。后来选择每个类依次使用6种颜色中的一种。相同的类会是同一颜色,距离得较远的但颜色相同应是属于不同类了。
PS:噪声点标记为黑色

import sklearn.cluster

Css=sklearn.cluster.DBSCAN(eps=0.50, min_samples=4).fit(otherdata)
ypred=np.array(Css.labels_)
ddraw=[]



colorset=[[222,0,0],[0,224,0],[0,255,255],[222,244,0],[255,0,255],[128,0,0]]
for cluuus in set(ypred):
    
    kaka=np.where(ypred==cluuus)
    ppk=open3d.geometry.PointCloud()
    ppk.points = open3d.utility.Vector3dVector(otherdata[kaka])

    c=colorset[cluuus%6]
    if cluuus==-1:
        c=[0,0,0]

    cs=np.tile(c,(otherdata[kaka].shape[0],1))
    ppk.colors=open3d.Vector3dVector(cs)
    ddraw.append(ppk)



ddraw.append(planepcd)
open3d.visualization.draw_geometries(ddraw)

图一
图二
图三
离雷达越远处的噪声越多,且聚类得较乱。但离雷达近处的聚类效果还可以,如图一小车与旁边的类似电线杆、供电箱被分成不同类。

在这里插入图片描述

可以调节DBSCAN的超参数以获得更好的聚类效果。

附其他点云数据的处理效果

在这里插入图片描述
在这里插入图片描述

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值