scipy.spatial参考博客:Python点云处理——建立KDtree

1 KDtree算法原理

KDtree构建出了一种类似于二叉树的树形数据存储结构,每一层都对应原始数据中相应的维度,以K层为一个循环,因此被称为KDtree。

2 计算过程

给出一组三维点云数据(1,1,1),(2,2,2),(1,3,1),(3,4,2),(4,5,6):

  1. 首先,x坐标划分,以2为分界,(2,2,2)为根节点,小于2的在左子树:(1,1,1),(1,3,1),大于2的在右子树:(3,4,2),(4,5,6)
  2. 然后以y坐标划分,前一层的左子树以1为分界,(1,1,1)在根节点,(1,3,1)在右子树;前一层右子树以4为分界,(3,4,2)在根节点,(4,5,6)在右子树,这样就将所有点云数据唯一地存储在了KDtree中

3 代码实现

import numpy as np
from scipy.spatial import KDTree

point= np.random.rand(1000,7)
tree = KDTree(point[:, 0:3])

先随机生成一个7维的点云数据(xyz坐标,xyz法向量,标签),然后调用Scipy中的scipy.spatial.KDTree库函数。与Open3D相比,该库函数可以生成任意维度的KDtree,而不是只能输入三维点云,在处理带有法向量和标签等其他维度的点云数据时具有天然的优势。

4 应用

生成KDtree后,最常见的应用就是对其进行各种搜索。

import numpy as np
from scipy.spatial import KDTree

point= np.random.rand(1000,7)
tree = KDTree(point[:, 0:3])

for i in range(0,len(point)):
    neighbors = tree.query_ball_point(point[i,0:3], 0.1,workers=-1,return_length=True)

这句代码调用了Scipy的KDtree模块中的“球查询”,即半径查找功能,可以查找点云中指定点在半径0.1内的所有近邻点,workers=-1代表启用多线程,poinr[i,0:3]代表只对前三列数据进行查找,若不指定return_lengeth参数,默认返回这些近邻点的索引。若指定其为True,则返回这些点的个数,从而便于进行滤波算法的构建。

最近邻:

matplotlib.pyplot参考博客:Python 数据分析(二):Matplotlib 绘图
只记录学习过程中常用的

1 简单使用

from matplotlib import pyplot as plt

x = range(1, 7)
y = [13, 15, 14, 16, 15, 17]
plt.title('折线图')
plt.xlabel('x 轴')
plt.ylabel('y 轴')
plt.plot(x, y)
plt.show()

【Python基础】—— scipy.spatial.KDTree、matplotlib.pyplot、imageio-LMLPHP
改变折线的样式、颜色等

from matplotlib import pyplot as plt

x = range(1, 7)
y = [13, 15, 14, 16, 15, 17]
'''
figsize:设置图片的宽、高,单位为英寸
dpi:设置分辨率
'''
plt.figure(figsize=(8, 5), dpi=80)
plt.title('折线图')
plt.xlabel('x 轴')
plt.ylabel('y 轴')
'''
color:颜色
linewidth:线的宽度
marker:折点样式
linestyle:线的样式,主要包括:'-'、'--'、'-.'、':'
'''
plt.plot(x, y, color='red', marker='o', linewidth='1', linestyle='--')
# 保存
plt.savefig('test.png')
plt.show()

【Python基础】—— scipy.spatial.KDTree、matplotlib.pyplot、imageio-LMLPHP

2 多线

from matplotlib import pyplot as plt

x = range(15, 25)
y1 = [50, 55, 58, 65, 70, 68, 70, 72, 75, 70]
y2 = [52, 53, 60, 63, 65, 68, 75, 80, 85, 72]
plt.figure(figsize=(10, 6), dpi=80)
plt.title('体重年龄折线图')
plt.xlabel('年龄(岁)')
plt.ylabel('体重(kg)')
plt.plot(x, y1, color='red', label='张三')
plt.plot(x, y2, color='blue', label='李四')
# 添加网格,alpha 为透明度
plt.grid(alpha=0.5)
# 添加图例
plt.legend(loc='upper right')
plt.show()

【Python基础】—— scipy.spatial.KDTree、matplotlib.pyplot、imageio-LMLPHP

3 子图

from matplotlib import pyplot as plt
import numpy as np

a = np.arange(1, 30)
# 划分子图
fig, axs = plt.subplots(2, 2)
# 绘制子图
axs1 = axs[0, 0]
axs2 = axs[0, 1]
axs3 = axs[1, 0]
axs4 = axs[1, 1]
axs1.plot(a, a)
axs2.plot(a, np.sin(a))
axs3.plot(a, np.log(a))
axs4.plot(a, a ** 2)
plt.show()

【Python基础】—— scipy.spatial.KDTree、matplotlib.pyplot、imageio-LMLPHP
imageio库参考博客:
【python】利用imageio库制作动态图
Python快速生成gif图
将多张图片合成GIF,需要的 python 库为 imageio,使用 imageio 可方便的使多张图片生成 gif 图。首先我们需要一个列表存储图片路径,此处为了方便演示,直接使用列表作为存储,并且创建一个变量为图片的保存路径:

import os
import imageio

frames = []
for image_name in os.listdir("./image"): # 读取image下的图片名称
    image_name = "D:\随笔\测试\image\\" + image_name # 绝对路径
    frames.append(imageio.imread(image_name))

imageio.mimsave("./res.gif", frames, 'GIF', duration=0.1) # 保存在当前文件夹
# 参数:duration=0.1,间隔时间

合成gif图

import imageio
def compose_gif():
    img_paths = ["img/1.jpg","img/2.jpg","img/3.jpg","img/4.jpg"
    ,"img/5.jpg","img/6.jpg"]
    gif_images = []
    for path in img_paths:
        gif_images.append(imageio.imread(path))
    imageio.mimsave("test.gif",gif_images,fps=1)
04-17 01:41