Skip to content

Commit

Permalink
Changed shortpath.py and created new example.
Browse files Browse the repository at this point in the history
- Added a new possible output to shortpath.py in order to debug the
graph generation.
- New example using this step-wise output from shortpath.py to create a
.gif of the graph creation.
  • Loading branch information
mattbv committed Aug 19, 2018
1 parent fedcf64 commit 634ead4
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 5 deletions.
3 changes: 2 additions & 1 deletion pc2graph/example_batch.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
from downsampling import (downsample_cloud, upsample_cloud)
import os


if __name__ == '__main__':

# Declaring list of files to process and output folder.
Expand Down Expand Up @@ -70,7 +71,7 @@

# Maximum distance between points. If distance > threshold, neighboring
# point is not added to graph.
nbrs_threshold = 0.08
nbrs_threshold = 0.15

# When initial growth process is broken (gap in the cloud) and no
# other point can be added, incease threshold to include missing points.
Expand Down
93 changes: 93 additions & 0 deletions pc2graph/example_plot_gif.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# Copyright (c) 2017, Matheus Boni Vicari, TLSeparation Project
# All rights reserved.
#
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

__author__ = "Matheus Boni Vicari"
__copyright__ = "Copyright 2017"
__credits__ = ["Matheus Boni Vicari"]
__license__ = "GPL3"
__version__ = "0.1"
__maintainer__ = "Matheus Boni Vicari"
__email__ = "[email protected]"
__status__ = "Development"


from downsampling import downsample_cloud
from shortpath import array_to_graph
import numpy as np
import glob
import os
import mayavi.mlab as mlab


if __name__ == '__main__':

# Setting up where to save the data.
out_folder = '../data/test_gif/'
out_file = 'test'
layer_delay = 2

# Setting up parameters to generate the graph.
point_cloud = np.loadtxt('../data/point_cloud_example.txt')
downsample_dist = 0.05
kpairs = 3
knn = 100
nbr_dist_threshold = downsample_dist * 1.5
nbr_dist_threshold_step = 0.03
downsample_cloud = downsample_cloud(point_cloud, downsample_dist)

# Obtaining base id (lowest point in the cloud).
base_id = np.argmin(downsample_cloud[:, 2])

# Generating graph with option to return the step_register as True.
G, step_register = array_to_graph(downsample_cloud, base_id, kpairs,
knn, nbr_dist_threshold,
nbr_dist_threshold_step,
return_step=True)


# Starts the iterative plotting. This will require the Mayavi package.
iteration = 0
mlab.figure(bgcolor=(1, 1, 1), fgcolor=(0, 0, 0))
mlab.points3d(downsample_cloud[:, 0], downsample_cloud[:, 1],
downsample_cloud[:, 2], color=(0.3, 0.3, 0.3), mode='point')
for s in np.unique(step_register):
mask = step_register == s
mlab.points3d(downsample_cloud[mask, 0], downsample_cloud[mask, 1],
downsample_cloud[mask, 2], color=(1, 0, 0), mode='point')
mlab.savefig(out_folder + '%s.png' % iteration)
iteration += 1
mlab.close()

# Generating the list of step images to join in a gif later.
file_list = glob.glob('%s*.png' % out_folder)
file_list = [os.path.basename(f) for f in file_list]
list.sort(file_list, key=lambda x: int(os.path.basename(x).split('.png')[0]))
with open('%simage_list.txt' % out_folder, 'w') as file:
for item in file_list:
file.write("%s\n" % item)

# Changing directory and using ImageMagik to join all images into a gif.
# Then, delets all unnecessary files.In the end, returns to initial
# directory.
cwd = os.getcwd()
os.chdir(out_folder)
os.system('convert -loop 0 -delay %s @image_list.txt %s.gif' % (layer_delay, out_file))
os.remove('image_list.txt')
for f in file_list:
os.remove(f)
os.chdir(cwd)

31 changes: 27 additions & 4 deletions pc2graph/shortpath.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@


def array_to_graph(arr, base_id, kpairs, knn, nbrs_threshold,
nbrs_threshold_step, graph_threshold=np.inf):
nbrs_threshold_step, graph_threshold=np.inf,
return_step=False):

"""
Converts a numpy.array of points coordinates into a Weighted BiDirectional
Expand Down Expand Up @@ -61,12 +62,18 @@ def array_to_graph(arr, base_id, kpairs, knn, nbrs_threshold,
graph_threshold : float
Maximum distance between pairs of nodes (edge distance) accepted in
the graph generation.
return_step : bool
Option to select if function should output the step register, which
can be used to debug the creationg of graph 'G'.
Returns
-------
G : networkx graph
Graph containing all points in 'arr' as nodes.
step_register : array
1D array with the same number of entries as 'arr'. Stores the step
number of which each point in 'arr' was added to 'G'.
"""

# Initializing graph.
Expand All @@ -88,9 +95,18 @@ def array_to_graph(arr, base_id, kpairs, knn, nbrs_threshold,
# and all ids already processed (processed_idx).
current_idx = [base_id]
processed_idx = [base_id]

# Setting up the register of at which step each point was added to the
# graph.
step_register = np.full(arr.shape[0], np.nan)
current_step = 0
step_register[base_id] = current_step

# Looping while there are still indices (idx) left to process.
while idx.shape[0] > 0:

# Increasing a single step count.
current_step += 1

# If current_idx is a list containing several indices.
if len(current_idx) > 0:
Expand Down Expand Up @@ -191,8 +207,15 @@ def array_to_graph(arr, base_id, kpairs, knn, nbrs_threshold,

# Generating list of remaining proints to process.
idx = idx_base[np.in1d(idx_base, processed_idx, invert=True)]

return G

# Adding new nodes to the step register.
current_idx = np.array(current_idx).astype(int)
step_register[current_idx] = current_step

if return_step is True:
return G, step_register
else:
return G


def extract_path_info(G, base_id, return_path=True):
Expand Down

0 comments on commit 634ead4

Please sign in to comment.