From 8c96a2c4529ca722d6084d3aa028da93f6d95a9d Mon Sep 17 00:00:00 2001
From: Maciej Wielgosz <maciej.wielgosz@nibio.no>
Date: Fri, 14 Oct 2022 08:53:26 +0200
Subject: [PATCH] remove small tiles

---
 nibio_preprocessing/remove_small_tiles.py | 52 ++++++++++++++++-------
 1 file changed, 37 insertions(+), 15 deletions(-)

diff --git a/nibio_preprocessing/remove_small_tiles.py b/nibio_preprocessing/remove_small_tiles.py
index 999fe4c..17be4f1 100644
--- a/nibio_preprocessing/remove_small_tiles.py
+++ b/nibio_preprocessing/remove_small_tiles.py
@@ -5,13 +5,19 @@ import plyfile
 
 
 class RemoveSmallTiles():
+    """
+    Works with ply files.
+    """
     def __init__(self, dir, min_density, tile_index_file, verbose=False):
         self.dir = dir
         self.min_size = min_density
         self.tile_index_file = tile_index_file
         self.verbose = verbose
         
-    def get_density_of_single_tile(self, tile_path):
+    def get_density_and_points_nr_of_single_tile(self, tile_path):
+        """
+        Get the density of a single tile.
+        """
         plydata = plyfile.PlyData.read(tile_path)
         volume = (plydata['vertex']['x'].max() - plydata['vertex']['x'].min()) \
         * (plydata['vertex']['y'].max() - plydata['vertex']['y'].min()) \
@@ -20,7 +26,7 @@ class RemoveSmallTiles():
         number_of_points = plydata['vertex'].count
         density = number_of_points / volume
 
-        return density
+        return density, number_of_points
 
     @staticmethod
     def remove_line_from_csv(path, line):
@@ -35,49 +41,65 @@ class RemoveSmallTiles():
                     f.write(lines[i])
 
     def get_density_of_all_tiles(self):
-        # read all the ply files in the folder
+        """
+        Get the density of all tiles in the directory.
+        """
         files = glob.glob(os.path.join(self.dir, "*.ply"))
 
         if self.verbose:
             print(f'Found {len(files)} tiles')
 
         # compute the density of each tile and put it in a dictionary toghehter with the file path
-        densities = {}
+        densities_and_point_nr = {}
         for i, ply in enumerate(files):
             # get a fine name without the path and suffix
             file_name = os.path.split(ply)[1].split('.')[0]
             # full path to the tile
             tile_path = os.path.join(self.dir, file_name + '.ply')
             # get the density of the tile
-            density = self.get_density_of_single_tile(ply)
+            density = self.get_density_and_points_nr_of_single_tile(ply)
             # put it into a tuple together with the file name
-            densities[i] = (file_name, tile_path, density)
+            densities_and_point_nr[i] = (file_name, tile_path, density[0], density[1])
 
         if self.verbose:
             print(f'Computed density of all tiles')
 
-        return densities
+        return densities_and_point_nr
+
 
     def remove_small_tiles(self):
+        """
+        Remove tiles that are too small.
+        """
         # get the density of all tiles
-        densities = self.get_density_of_all_tiles()
+        densities_and_point_nr = self.get_density_of_all_tiles()
 
-        # remove the tiles that are too small
-        for i, density in densities.items():
-            if density[2] < self.min_size:
+        # remove the tiles that whicha are too small (points per m^3)
+        for i, density in densities_and_point_nr.items():
+            if density[3] < 10000:
                 if self.verbose:
-                    print(f'Removing tile {density[0]} with density {density[2]}')
+                    print(f'Removing {density[1]} which has only {density[3]} points')
                 os.remove(density[1])
                 self.remove_line_from_csv(self.tile_index_file, i)
 
+        # remove the tiles that of a small density
+        for i, density in densities_and_point_nr.items():
+            if density[2] < self.min_size:
+                if self.verbose:
+                    print(f'Removing tile {density[0]} with density {density[2]}')
+                # check if the tile is already removed
+                if os.path.exists(density[1]):
+                    os.remove(density[1])
+                    self.remove_line_from_csv(self.tile_index_file, i)
+
         # if verbose print the lowest and the highest density along with the tile name
         if self.verbose:
-            print(f'Lowest density: {min(densities.values(), key=lambda x: x[2])}')
-            print(f'Highest density: {max(densities.values(), key=lambda x: x[2])}')
+            print(f'Lowest density: {min(densities_and_point_nr.values(), key=lambda x: x[2])}')
+            print(f'Highest density: {max(densities_and_point_nr.values(), key=lambda x: x[2])}')
 
         # if verbose print the number of tiles that were removed
         if self.verbose:
-            print(f'Removed {len(densities) - len(glob.glob(os.path.join(self.dir, "*.ply")))} tiles')
+            print(f'Removed {len(densities_and_point_nr) - len(glob.glob(os.path.join(self.dir, "*.ply")))} tiles')
 
     def main(self):
         self.remove_small_tiles()
-- 
GitLab