{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# How to sample from a mesh?" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "from geomfum.dataset import NotebooksDataset\n", "from geomfum.metric.mesh import (\n", " GraphShortestPathMetric,\n", " HeatDistanceMetric,\n", " VertexEuclideanMetric,\n", ")\n", "from geomfum.plot import MeshPlotter\n", "from geomfum.sample import FarthestPointSampler, PoissonSampler, VertexProjectionSampler\n", "from geomfum.shape import TriangleMesh\n" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "dataset = NotebooksDataset()\n", "mesh = TriangleMesh.from_file(dataset.get_filename(\"cat-00\"))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## \"Coordinate\" samplers\n", "\n", "If we're interested in sampling coordinates of points on the mesh, we can use `PoissonSampler`.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "poisson_sampler = PoissonSampler.from_registry(min_n_samples=3, which=\"pymeshlab\")\n", "sampled_vertices = poisson_sampler.sample(mesh)\n", "sampled_vertices" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Vertex indices samplers\n", "\n", "If we're interested in sampling vertex indices instead, we can leverage \"coordinate\" samplers like `PoissonSampler` by projecting the coordinates to the closest vertices." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "vertex_sampler = VertexProjectionSampler(sampler=poisson_sampler)\n", "sampled_indices = vertex_sampler.sample(mesh)\n", "sampled_indices.astype(int)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To get vertex coordinates." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sampled_vertices = mesh.vertices[sampled_indices]\n", "sampled_vertices" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's visualize the sampled points" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plotter = MeshPlotter.from_registry(colormap=\"RdBu\", which=\"plotly\")\n", "plotter.add_mesh(mesh)\n", "plotter.highlight_vertices(sampled_vertices)\n", "plotter.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Farthest point sampler\n", "\n", "Alternatively, we can sample vertex indices directly with `FarthestPointSampler`. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Select the metrics." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "metrics = {\n", " \"euclidean\": VertexEuclideanMetric,\n", " \"heat-distance\": HeatDistanceMetric,\n", " \"graph\": GraphShortestPathMetric,\n", "}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The vertex **7181** corresponds to the extreme of the cat’s tail. We start to sample from this point.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fps = {}\n", "samp = FarthestPointSampler(6,)\n", "\n", "for name, metric in metrics.items():\n", " mesh.equip_with_metric(metric)\n", " samples = samp.sample(mesh, first_point= 7181)\n", " fps[name] = samples\n", " print(f\"FPS {name}: {samples}\")\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's visualize the sampled points" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plotter = MeshPlotter.from_registry(colormap=\"RdBu\", which=\"plotly\")\n", "plotter.add_mesh(mesh)\n", "plotter.highlight_vertices(mesh.vertices[fps['euclidean']])\n", "plotter.show()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plotter = MeshPlotter.from_registry(colormap=\"RdBu\", which=\"pyvista\")\n", "plotter.add_mesh(mesh)\n", "plotter.highlight_vertices(mesh.vertices[fps['heat-distance']])\n", "plotter.show()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "metric = list(fps.keys())[0]\n", "plotter = MeshPlotter.from_registry(colormap=\"RdBu\", which=\"polyscope\")\n", "plotter.add_mesh(mesh)\n", "plotter.highlight_vertices(mesh.vertices[fps['graph']],)\n", "#plotter.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Sampling from a subset\n", "\n", "The vertex **4265** corresponds to the extreme of the cat’s muzzle, i want to select the FPs on the tail." ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [], "source": [ "points_on_the_tail = list(range(len(mesh.vertices) - 100, len(mesh.vertices)))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fps = {}\n", "dataset = NotebooksDataset()\n", "samp = FarthestPointSampler(6,)\n", "for name, metric in metrics.items():\n", " mesh.equip_with_metric(metric)\n", " samples = samp.sample(mesh, points_pool = points_on_the_tail, first_point= 4265)\n", " fps[name] = samples\n", " print(f\"FPS {name}: {samples}\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plotter = MeshPlotter.from_registry(colormap=\"RdBu\", which=\"plotly\")\n", "plotter.add_mesh(mesh)\n", "plotter.highlight_vertices(mesh.vertices[fps['euclidean']])\n", "plotter.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Further reading\n", "\n", "* [How to compute descriptors?](./03_descriptors.ipynb)\n", "\n", "* [How to set landmarks?](./06_landmarks.ipynb)" ] } ], "metadata": { "kernelspec": { "display_name": "py12", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.3" } }, "nbformat": 4, "nbformat_minor": 2 }