easyidp.pointcloud.PointCloud¶
- class easyidp.pointcloud.PointCloud(pcd_path='', offset=[0.0, 0.0, 0.0])¶
EasyIDP定义的PointCloud类,由点坐标以及可选的点颜色和点法线组成。
- __init__(pcd_path='', offset=[0.0, 0.0, 0.0])¶
初始化PointCloud类的方法
- 参数:
pcd_path (str, optional) -- 用于加载/读取的点云文件路径,默认值为"",表示创建一个空的点云类
offset (list, optional) -- 此参数用于指定您自己的偏移量,而不是自动计算的偏移量。 .. 注意:: 当点云xyz值过大时,需要扣除重复值(减去偏移量)以节省内存成本并提高精度。 .. 警告:: 对于某些Pix4D生成的点云,点云本身已被偏移,需要手动添加偏移值。
示例
准备
取消numpy科学计数法显示:
>>> import numpy as np >>> np.set_printoptions(suppress=True)
包加载:
>>> import easyidp as idp >>> test_data = idp.data.TestData()
读取大型xyz点云
大多数点云直接使用CRS(GPS)坐标作为xyz值。
>>> pcd = idp.PointCloud(test_data.pcd.maize_las) >>> pcd.points array([[ 367993.0206, 3955865.095 , 57.9707], [ 367993.146 , 3955865.3131, 57.9703], [ 367992.6317, 3955867.2979, 57.9822], ..., [ 368014.7912, 3955879.4943, 58.0219], [ 368014.1528, 3955883.5785, 58.0321], [ 368016.7278, 3955874.1188, 57.9668]])
如果直接存储这些值,将会消耗大量内存并且精度会降低。但通过偏移,这些数据可以更整齐地存储在EasyIDP中:
>>> pcd.offset array([ 367900., 3955800., 0.]) >>> pcd._points array([[ 93.0206, 65.095 , 57.9707], [ 93.146 , 65.3131, 57.9703], [ 92.6317, 67.2979, 57.9822], ..., [114.7912, 79.4943, 58.0219], [114.1528, 83.5785, 58.0321], [116.7278, 74.1188, 57.9668]])
手动指定偏移量
之前的偏移量由EasyIDP自动计算,您也可以手动指定偏移量:
>>> pcd = idp.PointCloud(test_data.pcd.maize_las, offset=[367800, 3955700, 50]) >>> pcd.offset array([ 367800., 3955700., 50.]) >>> pcd._points array([[193.0206, 165.095 , 7.9707], [193.146 , 165.3131, 7.9703], [192.6317, 167.2979, 7.9822], ..., [214.7912, 179.4943, 8.0219], [214.1528, 183.5785, 8.0321], [216.7278, 174.1188, 7.9668]])
尽管内部存储的值发生了变化,但这不会影响最终的点值:
>>> pcd.points array([[ 367993.0206, 3955865.095 , 57.9707], [ 367993.146 , 3955865.3131, 57.9703], [ 367992.6317, 3955867.2979, 57.9822], ..., [ 368014.7912, 3955879.4943, 58.0219], [ 368014.1528, 3955883.5785, 58.0321], [ 368016.7278, 3955874.1188, 57.9668]])
读取Pix4D偏移的点云并添加偏移值回去
如果您直接读取Pix4D生成的点云:
>>> pcd = idp.PointCloud(test_data.pcd.lotus_ply_bin) >>> pcd x y z r g b nx ny nz 0 -18.908 -15.778 -0.779 123 103 79 nodata nodata nodata 1 -18.908 -15.777 -0.78 124 104 81 nodata nodata nodata 2 -18.907 -15.775 -0.802 123 103 80 nodata nodata nodata ... ... ... ... ... ... ... ... ... ... 42451 -15.789 -17.961 -0.847 116 98 80 nodata nodata nodata 42452 -15.789 -17.939 -0.84 113 95 76 nodata nodata nodata 42453 -15.786 -17.937 -0.833 115 97 78 nodata nodata nodata
这里的xyz值似乎不正确,当我们检查param文件夹中的Pix4D项目``{name}_offset.xyz``文件时,我们可以找到Pix4D存储的偏移值。
>>> with open(test_data.pix4d.lotus_param / "hasu_tanashi_20170525_Ins1RGB_30m_offset.xyz", 'r') as f: ... f.readlines() ['368043.000 3955495.000 98.000']
这通常需要用户手动将偏移值添加回点云。但EasyIDP支持轻松处理这种情况:
>>> p4d_offset_np = np.array([368043, 3955495, 98]) >>> pcd = idp.PointCloud(test_data.pcd.lotus_ply_bin, p4d_offset_np) >>> pcd x y z r g b nx ny nz 0 368024.092 3955479.222 97.221 123 103 79 nodata nodata nodata 1 368024.092 3955479.223 97.22 124 104 81 nodata nodata nodata 2 368024.093 3955479.225 97.198 123 103 80 nodata nodata nodata ... ... ... ... ... ... ... ... ... ... 42451 368027.211 3955477.039 97.153 116 98 80 nodata nodata nodata 42452 368027.211 3955477.061 97.16 113 95 76 nodata nodata nodata 42453 368027.214 3955477.063 97.167 115 97 78 nodata nodata nodata
备注
您还可以通过
easyidp.Pix4D对象获取p4d_offset_np:>>> p4d = idp.Pix4D(project_path = test_data.pix4d.lotus_folder, ... raw_img_folder = test_data.pix4d.lotus_photos, ... param_folder = test_data.pix4d.lotus_param)) >>> p4d.offset_np array([ 368043., 3955495., 98.])
并将其传递给前面的函数:
>>> pcd = idp.PointCloud(test_data.pcd.lotus_ply_bin, p4d.offset_np)
Methods
__init__([pcd_path, offset])初始化PointCloud类的方法
change_crs(target_crs)Change the point cloud coordinate system
clear()删除所有点并创建一个空的点云
crop_point_cloud(polygon_xy)沿着z轴切点云
crop_polygon(polygon_xy)Get all points inside a 2D polygon.
crop_rois(roi[, save_folder])通过给定的<ROI>或具有多个多边形和多边形名称的字典对象,沿z轴裁剪多个ROI
如果点云包含点颜色,则返回True。
如果点云包含点法线,则返回True。
如果点云包含点,则返回True。
read_point_cloud(pcd_path)打开一个新的点云文件以覆盖当前文件,支持ply、laz和las格式。
save(pcd_path)将当前点云保存到文件,支持ply、las、laz格式。
update_offset_value(off_val)更改偏移值而不影响xyz点值。
write_point_cloud(pcd_path)将当前点云保存到文件,支持ply、las、laz格式。
Attributes
The Coordinate Reference System (CRS) of point cloud
点云的偏移值
点云的xyz值
The 2D KDTree of point cloud for fast spatial query
当前点云文件的文件路径
当前点云文件的文件扩展名
点云的颜色(RGB)值
点云的法向量值
点云的大小(xyz)
- change_crs(target_crs)¶
Change the point cloud coordinate system
- 参数:
target_crs (pyproj.CRS)
- clear()¶
删除所有点并创建一个空的点云
- colors¶
点云的颜色(RGB)值
- crop_point_cloud(polygon_xy)¶
沿着z轴切点云
- 参数:
polygon_xy (nx2 ndarray) -- 多边形的xy坐标
- 返回类型:
<easyidp.PointCloud> object, The cropped point cloud
示例
数据准备:
>>> import easyidp as idp >>> test_data = idp.data.TestData() >>> pcd = idp.PointCloud(test_data.pcd.lotus_ply_bin) >>> polygon = np.array([ ... [-18.42576599, -16.10819054], ... [-18.00066757, -18.05295944], ... [-16.05021095, -17.63488388], ... [-16.46848488, -15.66774559], ... [-18.42576599, -16.10819054]])
运行此函数:
>>> cropped = pcd.crop_point_cloud(polygon) >>> cropped x y z r g b nx ny nz 0 -18.417 -16.119 -0.641 nodata nodata nodata nodata nodata nodata 1 -18.409 -16.169 -0.647 nodata nodata nodata nodata nodata nodata 2 -18.404 -16.142 -0.634 nodata nodata nodata nodata nodata nodata ... ... ... ... ... ... ... ... ... ... 22419 -16.065 -17.607 -0.699 nodata nodata nodata nodata nodata nodata 22420 -16.062 -17.578 -0.678 nodata nodata nodata nodata nodata nodata 22421 -16.051 -17.632 -0.692 nodata nodata nodata nodata nodata nodata
- crop_polygon(polygon_xy)¶
Get all points inside a 2D polygon.
Uses KDTree with bounding box pre-filtering for fast spatial query, then applies exact polygon containment test.
- 参数:
polygon_xy (np.ndarray) -- A 2D polygon coordinates with shape (n, 2), representing the boundary vertices in XY plane. The polygon should be closed (first and last point can be same or different).
- 返回:
The xyz coordinates of points inside the polygon, shape (m, 3). Returns empty array with shape (0, 3) if no points found.
- 返回类型:
np.ndarray
示例
>>> import easyidp as idp >>> pcd = idp.PointCloud("path/to/pointcloud.ply") >>> polygon = np.array([ ... [100.0, 200.0], ... [110.0, 200.0], ... [110.0, 210.0], ... [100.0, 210.0], ... [100.0, 200.0] ... ]) >>> xyz_inside = pcd.crop_polygon(polygon) >>> z_values = xyz_inside[:, 2]
- crop_rois(roi, save_folder=None)¶
通过给定的<ROI>或具有多个多边形和多边形名称的字典对象,沿z轴裁剪多个ROI
- 参数:
roi (easyidp.ROI | dict) --
由easyidp.ROI()创建的<ROI>对象或者键为roi名称,值为坐标的字典对象is_geo (bool, optional) -- 给定的多边形是 imarray 上的像素坐标还是地理坐标(默认)
save_folder (str, optional) -- 保存裁剪图像的文件夹,使用ROI索引作为文件名,默认值为None,表示不保存。
- 返回类型:
dict, The dictionary with key as roi name and value as <idp.PointCloud> object
示例
数据准备:
>>> import easyidp as idp >>> test_data = idp.data.TestData() >>> roi = idp.ROI(test_data.shp.lotus_shp, name_field=0) >>> roi = roi[0:3] >>> dom = idp.GeoTiff(test_data.pix4d.lotus_dom) >>> roi.change_crs(dom.crs) <easyidp.ROI> with 3 items [0] N1W1 array([[ 368017.7565143 , 3955511.08102276], [ 368019.70190232, 3955511.49811902], [ 368020.11263046, 3955509.54636219], [ 368018.15769062, 3955509.13563382], [ 368017.7565143 , 3955511.08102276]]) [1] N1W2 array([[ 368018.20042946, 3955508.96051697], [ 368020.14581791, 3955509.37761334], [ 368020.55654627, 3955507.42585654], [ 368018.601606 , 3955507.01512806], [ 368018.20042946, 3955508.96051697]]) [2] N1W3 array([[ 368018.64801755, 3955506.84956301], [ 368020.59340644, 3955507.26665948], [ 368021.00413502, 3955505.31490271], [ 368019.04919431, 3955504.90417413], [ 368018.64801755, 3955506.84956301]]) >>> pcd = idp.PointCloud(test_data.pix4d.lotus_pcd, offset=[368043, 3955495, 98]) x y z r g b nx ny nz 0 368014.849 3955511.333 97.215 51 55 33 nodata nodata nodata 1 368014.853 3955511.352 97.239 49 52 33 nodata nodata nodata 2 368014.865 3955511.485 97.402 46 50 30 nodata nodata nodata ... ... ... ... ... ... ... ... ... ... 6235710 368055.047 3955482.412 96.997 173 168 170 nodata nodata nodata 6235711 368055.051 3955482.407 97.051 154 140 129 nodata nodata nodata 6235712 368055.058 3955482.373 97.107 114 93 72 nodata nodata nodata
运行此函数:
>>> out = pcd.crop_rois(roi) >>> out {'N1W1': <easyidp.PointCloud class>, 'N1W2': <easyidp.PointCloud class>, 'N1W3': <easyidp.PointCloud class>}
您还可以通过以下方式将输出点云保存到给定文件夹:
>>> out = pcd.crop_rois(roi, save_folder=r'path/to/save/folder/')
- property crs¶
The Coordinate Reference System (CRS) of point cloud
- file_ext¶
当前点云文件的文件扩展名
- file_path¶
当前点云文件的文件路径
- has_colors()¶
如果点云包含点颜色,则返回True。
- 返回类型:
bool
- has_normals()¶
如果点云包含点法线,则返回True。
- 返回类型:
bool
- has_points()¶
如果点云包含点,则返回True。
- 返回类型:
bool
- normals¶
点云的法向量值
- property offset¶
点云的偏移值
小心
如果直接更改此值,点云的xyz值也会更改,就像移动整个点云一样。
示例
例如,点云像这样:
>>> import easyidp as idp >>> test_data = idp.data.TestData() >>> pts = idp.PointCloud(test_data.pcd.maize_las) >>> pts x y z r g b 0 367993.021 3955865.095 57.971 28 21 17 1 367993.146 3955865.313 57.97 28 23 19 2 367992.632 3955867.298 57.982 29 22 18 ... ... ... ... ... ... ... 49655 368014.791 3955879.494 58.022 33 28 25 49656 368014.153 3955883.578 58.032 30 40 26 49657 368016.728 3955874.119 57.967 25 20 18 >>> pts.offset array([ 367900., 3955800., 0.])
直接更改偏移量:
>>> pts.offset = [300, 200, 50] >>> pts x y z r g b 0 393.021 265.095 107.971 28 21 17 1 393.146 265.313 107.97 28 23 19 2 392.632 267.298 107.982 29 22 18 ... ... ... ... ... ... ... 49655 414.791 279.494 108.022 33 28 25 49656 414.153 283.578 108.032 30 40 26 49657 416.728 274.119 107.967 25 20 18
小心
如果您想更改偏移量而不影响点xyz值,请使用
update_offset_value()
- property points¶
点云的xyz值
- read_point_cloud(pcd_path)¶
打开一个新的点云文件以覆盖当前文件,支持ply、laz和las格式。
小心
此操作将完全清除当前点云的所有数据,并重新打开一个新的点云。
- 参数:
pcd_path (str | pathlib.Path) -- 要打开的点云文件的路径
示例
数据准备:
>>> import easyidp as idp >>> test_data = idp.data.TestData() >>> aaa = idp.PointCloud(test_data.pcd.maize_las) >>> aaa x y z r g b nx ny nz 0 367993.021 3955865.095 57.971 28 21 17 -0.031496062992125984 0.36220472440944884 0.9291338582677166 1 367993.146 3955865.313 57.97 28 23 19 0.08661417322834646 0.07086614173228346 0.9921259842519685 2 367992.632 3955867.298 57.982 29 22 18 -0.007874015748031496 0.26771653543307083 0.9606299212598425 ... ... ... ... ... ... ... ... ... ... 49655 368014.791 3955879.494 58.022 33 28 25 0.44881889763779526 -0.14960629921259844 0.8740157480314961 49656 368014.153 3955883.578 58.032 30 40 26 0.44881889763779526 -0.29133858267716534 0.8346456692913385 49657 368016.728 3955874.119 57.967 25 20 18 0.3228346456692913 0.26771653543307083 0.8976377952755905
此操作将完全覆盖之前的点云
>>> aaa.read_point_cloud(test_data.pcd.lotus_las) >>> aaa x y z r g b nx ny nz 0 -18.908 -15.778 -0.779 123 103 79 nodata nodata nodata 1 -18.908 -15.777 -0.78 124 104 81 nodata nodata nodata 2 -18.907 -15.775 -0.802 123 103 80 nodata nodata nodata ... ... ... ... ... ... ... ... ... ... 42451 -15.789 -17.961 -0.847 116 98 80 nodata nodata nodata 42452 -15.789 -17.939 -0.84 113 95 76 nodata nodata nodata 42453 -15.786 -17.937 -0.833 115 97 78 nodata nodata nodata
- save(pcd_path)¶
将当前点云保存到文件,支持ply、las、laz格式。
- 参数:
pcd_path (str) -- 保存的点云文件的路径,如果未给出文件扩展名,将使用父点云文件扩展名。
- shape¶
点云的大小(xyz)
- property tree¶
The 2D KDTree of point cloud for fast spatial query
- update_offset_value(off_val)¶
更改偏移值而不影响xyz点值。
- 参数:
off_val (list | tuple | ndarray) -- 要设置的偏移值
示例
例如,点云像这样:
>>> import easyidp as idp >>> test_data = idp.data.TestData() >>> pts = idp.PointCloud(test_data.pcd.maize_las) >>> pts x y z r g b 0 367993.021 3955865.095 57.971 28 21 17 1 367993.146 3955865.313 57.97 28 23 19 2 367992.632 3955867.298 57.982 29 22 18 ... ... ... ... ... ... ... 49655 368014.791 3955879.494 58.022 33 28 25 49656 368014.153 3955883.578 58.032 30 40 26 49657 368016.728 3955874.119 57.967 25 20 18 >>> pts.offset array([ 367900., 3955800., 0.])
更改偏移量而不影响xyz值:
>>> pts.update_offset_value([360000, 3955000, 50]) >>> pts.offset array([ 360000., 3955000., 50.]) >>> pts.points x y z r g b nx ny nz 0 367993.021 3955865.095 57.971 28 21 17 -0.031496062992125984 0.36220472440944884 0.9291338582677166 1 367993.146 3955865.313 57.97 28 23 19 0.08661417322834646 0.07086614173228346 0.9921259842519685 2 367992.632 3955867.298 57.982 29 22 18 -0.007874015748031496 0.26771653543307083 0.9606299212598425 ... ... ... ... ... ... ... ... ... ... 49655 368014.791 3955879.494 58.022 33 28 25 0.44881889763779526 -0.14960629921259844 0.8740157480314961 49656 368014.153 3955883.578 58.032 30 40 26 0.44881889763779526 -0.29133858267716534 0.8346456692913385 49657 368016.728 3955874.119 57.967 25 20 18 0.3228346456692913 0.26771653543307083 0.8976377952755905
小心
如果您想更改偏移量如同移动点云(也更改xyz值),请使用
offset()
- write_point_cloud(pcd_path)¶
将当前点云保存到文件,支持ply、las、laz格式。
- 参数:
pcd_path (str) -- 保存的点云文件的路径,如果未给出文件扩展名,将使用父点云文件扩展名。
示例
数据准备:
>>> import easyidp as idp >>> test_data = idp.data.TestData() >>> pcd = idp.PointCloud(test_data.pcd.lotus_ply_bin) >>> polygon = np.array([ ... [-18.42576599, -16.10819054], ... [-18.00066757, -18.05295944], ... [-16.05021095, -17.63488388], ... [-16.46848488, -15.66774559], ... [-18.42576599, -16.10819054]]) >>> cropped = pcd.crop_point_cloud(polygon) >>> cropped x y z r g b nx ny nz 0 -18.417 -16.119 -0.641 nodata nodata nodata nodata nodata nodata 1 -18.409 -16.169 -0.647 nodata nodata nodata nodata nodata nodata 2 -18.404 -16.142 -0.634 nodata nodata nodata nodata nodata nodata ... ... ... ... ... ... ... ... ... ... 22419 -16.065 -17.607 -0.699 nodata nodata nodata nodata nodata nodata 22420 -16.062 -17.578 -0.678 nodata nodata nodata nodata nodata nodata 22421 -16.051 -17.632 -0.692 nodata nodata nodata nodata nodata nodata
Use this function:
>>> cropped.write_point_cloud(r"path/to/save/pointcloud.ply")