|
51 | 51 |
|
52 | 52 | import pandas as pd |
53 | 53 | import simpledbf |
| 54 | +from plyfile import PlyData |
| 55 | +from pyntcloud import PyntCloud |
| 56 | +import open3d as o3d |
54 | 57 |
|
55 | 58 |
|
56 | 59 | gdal.UseExceptions() |
@@ -1439,140 +1442,121 @@ def get_training(inShape, inRas, bands, field, outFile = None): |
1439 | 1442 |
|
1440 | 1443 | return outData, rejects |
1441 | 1444 |
|
| 1445 | +def ply_features(incld, outcld=None): |
1442 | 1446 |
|
1443 | | -def get_training_point(inShape, inRas, bands, field): |
1444 | | - """ Collect training as a np array for use with create model function using |
1445 | | - point data |
1446 | | - |
1447 | | - Parameters |
1448 | | - -------------- |
1449 | | - |
1450 | | - inShape : string |
1451 | | - the input shapefile - must be esri .shp at present |
1452 | | - |
1453 | | - inRas : string |
1454 | | - the input raster from which the training is extracted |
1455 | | - |
1456 | | - bands : int |
1457 | | - no of bands |
1458 | | - |
1459 | | - field : string |
1460 | | - the attribute field containing the training labels |
| 1447 | + """ |
| 1448 | + Calculate point cloud features and write to file |
1461 | 1449 | |
1462 | | - outFile : string (optional) |
1463 | | - path to the training file saved as joblib format (eg - 'training.gz') |
1464 | 1450 | |
1465 | | - Returns |
1466 | | - --------------------- |
| 1451 | + Parameters |
| 1452 | + ----------- |
1467 | 1453 | |
1468 | | - A tuple containing: |
1469 | | - -np array of training data |
1470 | | - -list of polygons with invalid geometry that were not collected |
| 1454 | + incld: string |
| 1455 | + the input point cloud |
| 1456 | + |
| 1457 | + outcld: string |
| 1458 | + the output point cloud |
| 1459 | + |
1471 | 1460 |
|
| 1461 | + """ |
1472 | 1462 |
|
1473 | | - UNFINISHED DO NOT USE |
1474 | | - |
| 1463 | + pcd = PyntCloud.from_file(incld) |
| 1464 | + #o3d.io.read_point_cloud(incld) |
| 1465 | + |
| 1466 | + #pcd.estimate_normals() |
1475 | 1467 |
|
1476 | | - """ |
1477 | | - #t0 = time() |
1478 | | - outData = list() |
1479 | | - print('Loading & prepping data') |
1480 | | - raster = gdal.Open(inRas) |
1481 | | - shp = ogr.Open(inShape) |
1482 | | - lyr = shp.GetLayer() |
1483 | | - labels = np.arange(lyr.GetFeatureCount()) |
1484 | | - rb = raster.GetRasterBand(1) |
1485 | | - rgt = raster.GetGeoTransform() |
1486 | | - mem_drv = ogr.GetDriverByName('Memory') |
1487 | | - driver = gdal.GetDriverByName('MEM') |
1488 | | - rejects = [] |
| 1468 | + #cloud = PyntCloud.from_instance("open3d", |
| 1469 | + |
| 1470 | + |
| 1471 | + pProps =['anisotropy', "curvature", "eigenentropy", "eigen_sum", "linearity", |
| 1472 | + "omnivariance", "planarity", "sphericity"]#, "inclination_deg", |
| 1473 | + # "inclination_rad", "orientation_deg", "orientation_rad"] |
| 1474 | + #, "HueSaturationValue",#"RelativeLuminance"," RGBIntensity"] |
| 1475 | + |
| 1476 | + k_neighbors = pcd.get_neighbors(k=30) |
| 1477 | + eigenvalues = pcd.add_scalar_field("eigen_values", k_neighbors=k_neighbors) |
| 1478 | + |
| 1479 | + [pcd.add_scalar_field(p, ev=eigenvalues) for p in pProps] |
1489 | 1480 |
|
1490 | | - print('getting points') |
1491 | | - for label in tqdm(labels): |
1492 | | - #print(label) |
1493 | | - feat = lyr.GetFeature(label) |
1494 | | - if feat == None: |
1495 | | - print('no geometry for feature '+str(label)) |
1496 | | - continue |
1497 | | - iD = feat.GetField(field) |
1498 | | - geom = feat.GetGeometryRef() |
1499 | | - mx,my=geom.GetX(), geom.GetY() #coord in map units |
| 1481 | + if outcld == None: |
| 1482 | + pcd.to_file(incld) |
| 1483 | + else: |
| 1484 | + pcd.to_file(outcld) |
1500 | 1485 |
|
1501 | | - #Convert from map to pixel coordinates. |
1502 | | - #Only works for geotransforms with no rotation. |
1503 | | - px = int((mx - gt[0]) / gt[1]) #x pixel |
1504 | | - py = int((my - gt[3]) / gt[5]) #y pixel |
| 1486 | +def get_training_ply(incld, label_field="scalar_label", outFile=None): |
1505 | 1487 |
|
1506 | | - structval=rb.ReadRaster(px, py,1,1,buf_type=gdal.GDT_UInt16) #Assumes 16 bit int aka 'short' |
1507 | | - intval = struct.unpack('h' , structval) #use the 'short' format code (2 bytes) not int (4 bytes) |
| 1488 | + """ |
| 1489 | + Get training from a point cloud |
1508 | 1490 | |
1509 | | - print(intval[0]) |
1510 | | - # Get raster georeference info |
1511 | | - |
1512 | | -# src_offset = bbox_to_pixel_offsets(rgt, geom) |
1513 | | -# |
1514 | | -# |
1515 | | -# # calculate new geotransform of the feature subset |
1516 | | -# new_gt = ( |
1517 | | -# (rgt[0] + (src_offset[0] * rgt[1])), |
1518 | | -# rgt[1], |
1519 | | -# 0.0, |
1520 | | -# (rgt[3] + (src_offset[1] * rgt[5])), |
1521 | | -# 0.0, |
1522 | | -# rgt[5]) |
1523 | | - |
1524 | | - |
1525 | | - # Create a temporary vector layer in memory |
1526 | | - mem_ds = mem_drv.CreateDataSource('out') |
1527 | | - mem_layer = mem_ds.CreateLayer('poly', None, ogr.wkbPolygon) |
1528 | | - mem_layer.CreateFeature(feat.Clone()) |
1529 | | - |
1530 | | - # Rasterize it |
1531 | | - rvds = driver.Create('', src_offset[2], src_offset[3], 1, gdal.GDT_Byte) |
1532 | | - rvds.SetGeoTransform(new_gt) |
1533 | | - gdal.RasterizeLayer(rvds, [1], mem_layer, burn_values=[1]) |
1534 | | - rv_array = rvds.ReadAsArray() |
1535 | | - |
1536 | | - # Mask the source data array with our current feature |
1537 | | - # we take the logical_not to flip 0<->1 to get the correct mask effect |
1538 | | - # we also mask out nodata values explictly |
1539 | | - |
| 1491 | + |
| 1492 | + Parameters |
| 1493 | + ----------- |
| 1494 | + |
| 1495 | + incld: string |
| 1496 | + the input point cloud |
| 1497 | + |
| 1498 | + label_field: string |
| 1499 | + the name of the field representing the training points which must |
| 1500 | + be positive integers |
| 1501 | + |
| 1502 | + outFile: string |
| 1503 | + path to training array to be saved as .gz via joblib |
| 1504 | + |
1540 | 1505 |
|
| 1506 | + """ |
| 1507 | + # TODO Clean up lack of loops funcs to do stuff |
| 1508 | + # classify ply TODO also |
| 1509 | + # convert Open3D.o3d.geometry to necessary vars |
| 1510 | + pcd = o3d.io.read_point_cloud(incld) |
| 1511 | + xyz = np.asarray(pcd.points) |
| 1512 | + cols = np.asarray(pcd.colors) |
| 1513 | + norms = np.asarray(pcd.normals) |
| 1514 | + pf = PlyData.read(incld) |
| 1515 | + |
| 1516 | +# pProps =['anisotropy', 'curvature', "eigenentropy", "eigen_sum", |
| 1517 | +# "linearity", "omnivariance", "planarity", "sphericity"] |
| 1518 | + |
| 1519 | + # doesn't matter if this is a float |
| 1520 | + label = np.array(pf.elements[0].data['scalar_label'], dtype='float64') |
| 1521 | + a = np.array(pf.elements[0].data['anisotropy(26)'], dtype='float64') |
| 1522 | + c = np.array(pf.elements[0].data["curvature(26)"], dtype='float64') |
| 1523 | + et = np.array(pf.elements[0].data["eigenentropy(26)"], dtype='float64') |
| 1524 | + es = np.array(pf.elements[0].data["eigen_sum(26)"], dtype='float64') |
| 1525 | + l = np.array(pf.elements[0].data["linearity(26)"], dtype='float64') |
| 1526 | + om = np.array(pf.elements[0].data["linearity(26)"], dtype='float64') |
| 1527 | + pl = np.array(pf.elements[0].data["omnivariance(26)"], dtype='float64') |
| 1528 | + sp = np.array(pf.elements[0].data["sphericity(26)"], dtype='float64') |
| 1529 | + |
| 1530 | + label.shape = (label.shape[0], 1) |
| 1531 | + a.shape=(label.shape[0], 1) |
| 1532 | + c.shape=(label.shape[0], 1) |
| 1533 | + et.shape=(label.shape[0], 1) |
| 1534 | + es.shape=(label.shape[0], 1) |
| 1535 | + l.shape=(label.shape[0], 1) |
| 1536 | + om.shape=(label.shape[0], 1) |
| 1537 | + pl.shape=(label.shape[0], 1) |
| 1538 | + sp.shape=(label.shape[0], 1) |
| 1539 | + |
| 1540 | + final = np.hstack((label, xyz, cols, norms, a, c, et, es, l, om, pl, sp)) |
| 1541 | + |
| 1542 | + # all these could be dumped now |
| 1543 | + del xyz, cols, norms, pf, a, c, et, es, l, om, pl, sp |
| 1544 | + |
| 1545 | + # prep for sklearn |
| 1546 | + X_train = final[final[:,0] >= 0] |
1541 | 1547 |
|
1542 | | - |
1543 | | - rb = raster.GetRasterBand(1) |
1544 | | - src_array = rb.ReadAsArray(src_offset[0], src_offset[1], src_offset[2], |
1545 | | - src_offset[3]) |
1546 | | - if np.shape(src_array) is (): |
1547 | | - rejects.append(label) |
1548 | | - continue |
1549 | | - # Read raster as arrays |
1550 | | - for band in range(1,bands+1): |
1551 | | - |
1552 | | - rb = raster.GetRasterBand(band) |
1553 | | - src_array = rb.ReadAsArray(src_offset[0], src_offset[1], src_offset[2], |
1554 | | - src_offset[3]) |
1555 | | - if src_array is None: |
1556 | | - src_array = rb.ReadAsArray(src_offset[0]-1, src_offset[1], src_offset[2], |
1557 | | - src_offset[3]) |
1558 | | - |
1559 | | - masked = np.ma.MaskedArray(src_array, |
1560 | | - mask=np.logical_or(src_array == 0, |
1561 | | - np.logical_not(rv_array))) |
1562 | | - |
1563 | | - |
1564 | | - datafinal = masked.flatten() |
| 1548 | + # Remove non-finite values |
| 1549 | + X_train = X_train[np.isfinite(X_train).all(axis=1)] |
| 1550 | + |
| 1551 | + # y labels |
| 1552 | + #y_train = X_train[:,0] |
| 1553 | + |
| 1554 | + if outFile != None: |
| 1555 | + jb.dump(X_train, outFile, compress=2) |
| 1556 | + |
| 1557 | + return X_train |
| 1558 | + |
1565 | 1559 |
|
1566 | | - if band == 1: |
1567 | | - X = np.zeros(shape = (datafinal.shape[0], bands+1)) |
1568 | | - X[:,0] = iD |
1569 | | - |
1570 | | - X[:,band] = datafinal |
1571 | | - #print(label,fieldval,xcount, ycount) |
1572 | | - outData.append(X) |
1573 | | - outData = np.asarray(outData) |
1574 | | - outData = np.concatenate(outData).astype(None) |
1575 | | - return outData, rejects |
1576 | 1560 |
|
1577 | 1561 |
|
1578 | 1562 | def rmse_vector_lyr(inShape, attributes): |
|
0 commit comments