Skip to content

Commit

Permalink
work with the distance matrix is moved to separate handlers
Browse files Browse the repository at this point in the history
  • Loading branch information
SVivdich02 committed Feb 25, 2024
1 parent 5010922 commit 968f361
Show file tree
Hide file tree
Showing 6 changed files with 148 additions and 94 deletions.
49 changes: 13 additions & 36 deletions example.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@
"points = np.asarray(pcd.points)\n",
"spatial_distance = cdist(points, points)\n",
"\n",
"dist, masks = sam_label_distance(points2instances, spatial_distance, 2, 10, 3)"
"dist, masks = sam_label_distance(points2instances, spatial_distance, 5, 10, 2)"
]
},
{
Expand All @@ -125,40 +125,16 @@
"metadata": {},
"outputs": [],
"source": [
"from src.utils.distances_utils import remove_isolated_points\n",
"from src.services.distance.isolated import RemovingIsolatedPointsProcessor\n",
"from src.services.distance.connected_component import ExtractionLargestConnectedComponentProcessor\n",
"\n",
"dist, points, trace = remove_isolated_points(dist, points, trace)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"dist.shape"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from src.utils.distances_utils import extract_largest_connected_component\n",
"distance_processors = [\n",
" RemovingIsolatedPointsProcessor(),\n",
" ExtractionLargestConnectedComponentProcessor(),\n",
"]\n",
"\n",
"dist_final, points_final, trace_final = extract_largest_connected_component(dist, points, trace)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(dist_final.shape)\n",
"print(len(points_final))\n",
"print(len(trace_final))"
"for processor in distance_processors:\n",
" dist, points, trace = processor.process(dist, points, trace)"
]
},
{
Expand All @@ -167,8 +143,9 @@
"metadata": {},
"outputs": [],
"source": [
"dist = dist_final\n",
"points = points_final"
"print(dist.shape)\n",
"print(len(points))\n",
"print(len(trace))"
]
},
{
Expand Down Expand Up @@ -207,7 +184,7 @@
"source": [
"from src.utils.pcd_utils import color_pcd_by_clusters_and_voxels\n",
"\n",
"pcd_colored = color_pcd_by_clusters_and_voxels(pcd_for_clustering, trace_final, clusters)"
"pcd_colored = color_pcd_by_clusters_and_voxels(pcd_for_clustering, trace, clusters)"
]
},
{
Expand Down
53 changes: 53 additions & 0 deletions src/services/distance/connected_component.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Copyright (c) 2023, Sofia Vivdich and Anastasiia Kornilova
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import copy
import numpy as np
import zope.interface

from src.services.distance.interface import IProcessor
from src.utils.distances_utils import dfs
from src.utils.pcd_utils import color_pcd_by_two_groups
from src.utils.pcd_utils import visualize_pcd


@zope.interface.implementer(IProcessor)
class ExtractionLargestConnectedComponentProcessor:
def process(self, distance_matrix, points, trace):
"""Extraction the largest connected component of a graph using the dfs algorithm"""

num_vertices = len(points)
half_num_vertices = num_vertices // 2
visited_vertices = np.array([False for i in range(num_vertices)], dtype=bool)
for i in range(num_vertices):
visited_vertices = dfs(distance_matrix, i)
if visited_vertices.sum() >= half_num_vertices:
break

not_visited_vertices = [
vertex for vertex, is_visited in enumerate(visited_vertices) if not is_visited
]

#Visualization of the extracted connectivity component against the background of the entire cloud
visualize_pcd(color_pcd_by_two_groups(points, not_visited_vertices))

trace_copy = copy.deepcopy(trace)
for index in sorted(not_visited_vertices, reverse=True):
del trace_copy[index]

return (
distance_matrix[visited_vertices][:, visited_vertices],
points[visited_vertices],
trace_copy,
)
25 changes: 25 additions & 0 deletions src/services/distance/interface.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Copyright (c) 2023, Sofia Vivdich and Anastasiia Kornilova
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import zope.interface


class IProcessor(zope.interface.Interface):
def process(distance_matrix, points, trace):
"""Extracting only those points that have certain properties
based on the distance matrix.
The result of processing is a distance matrix, a set of points
and a trace that contains only those points that satisfy the desired property.
"""
42 changes: 42 additions & 0 deletions src/services/distance/isolated.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Copyright (c) 2023, Sofia Vivdich and Anastasiia Kornilova
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import copy
import numpy as np
import zope.interface

from src.services.distance.interface import IProcessor


@zope.interface.implementer(IProcessor)
class RemovingIsolatedPointsProcessor:
def process(self, distance_matrix, points, trace):
"""Removing isolated points that have all 0s in the distance matrix except the diagonal element"""

mask_isolated = np.all(distance_matrix - np.eye(distance_matrix.shape[0]) == 0, axis=1)
isolated_points = np.array([i for i in range(len(points))], dtype=int)[
mask_isolated
]

trace_copy = copy.deepcopy(trace)
for index in sorted(isolated_points, reverse=True):
del trace_copy[index]

mask_not_isolated = np.any(distance_matrix - np.eye(distance_matrix.shape[0]) != 0, axis=1)

return (
distance_matrix[mask_not_isolated][:, mask_not_isolated],
points[mask_not_isolated],
trace_copy,
)
48 changes: 0 additions & 48 deletions src/utils/distances_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import copy
import numpy as np


Expand Down Expand Up @@ -64,53 +63,6 @@ def sam_label_distance(
return label_distance, mask


def remove_isolated_points(dist, points, trace):
"""Removing isolated points that have all 0s in the distance matrix except the diagonal element"""

mask_isolated = np.all(dist - np.eye(dist.shape[0]) == 0, axis=1)
isolated_points = np.array([i for i in range(len(points))], dtype=int)[
mask_isolated
]

trace_copy = copy.deepcopy(trace)
for index in sorted(isolated_points, reverse=True):
del trace_copy[index]

mask_not_isolated = np.any(dist - np.eye(dist.shape[0]) != 0, axis=1)

return (
dist[mask_not_isolated][:, mask_not_isolated],
points[mask_not_isolated],
trace_copy,
)


def extract_largest_connected_component(dist, points, trace):
"""Selection the largest connected component of a graph using the dfs algorithm"""

num_vertices = len(points)
half_num_vertices = num_vertices // 2
visited_vertices = np.array([False for i in range(num_vertices)], dtype=bool)
for i in range(num_vertices):
visited_vertices = dfs(dist, i)
if visited_vertices.sum() >= half_num_vertices:
break

not_visited_vertices = [
vertex for vertex, is_visited in enumerate(visited_vertices) if not is_visited
]

trace_copy = copy.deepcopy(trace)
for index in sorted(not_visited_vertices, reverse=True):
del trace_copy[index]

return (
dist[visited_vertices][:, visited_vertices],
points[visited_vertices],
trace_copy,
)


def dfs(distance_matrix, start_vertex):
num_vertices = len(distance_matrix)
visited = np.array([False for i in range(num_vertices)], dtype=bool)
Expand Down
25 changes: 15 additions & 10 deletions src/utils/pcd_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,25 +91,30 @@ def get_visible_points(pcd_centered, visualize=False):


def color_pcd_by_two_groups(points, indices):
colors = generate_random_colors(2)
"""Cloud coloring by group of given indices and remaining indices at points
Parameters
----------
points : numpy.array
points of the cloud to be colored
indices : numpy.array
indices of points that belong to the same group
"""

pcd = o3d.geometry.PointCloud()
pcd.points = o3d.utility.Vector3dVector(np.asarray(points))

pcd_colored = copy.deepcopy(pcd)
pcd_colored.colors = o3d.utility.Vector3dVector(
pcd.colors = o3d.utility.Vector3dVector(
np.zeros(np.asarray(pcd.points).shape)
)

points = pcd_colored.points

for i in range(len(points)):
pcd_colored.colors[i] = colors[0]
colors = generate_random_colors(2)
for i in range(len(pcd.points)):
pcd.colors[i] = colors[1]

for i in range(len(indices)):
pcd_colored.colors[indices[i]] = colors[1]
pcd.colors[indices[i]] = colors[0]

return pcd_colored
return pcd


def color_pcd_by_labels(pcd, labels):
Expand Down

0 comments on commit 968f361

Please sign in to comment.