import plotly.express as px
import plotly.io as pio
import torch
from kornia.core import stack
from kornia.geometry.liegroup import So3
from kornia.geometry.plane import Hyperplane, fit_plane
from kornia.geometry.vector import Vector3
from kornia.utils import create_meshgrid
Fit plane tutorial
Basic
Plane
kornia.geometry
This tutorial use shows how to generate a plane based on a mesh. Using the
Hyperplane
and Hyperplane
from kornia.gemetry.plane
. As data structure we use kornia.geometry.liegroup.So3
e kornia.geometry.vector.Vector3
# define the plane
= 25
plane_h = 50
plane_w
# create a base mesh in the ground z == 0
= create_meshgrid(plane_h, plane_w, normalized_coordinates=True)
mesh = mesh[..., 0], mesh[..., 1]
X, Y = 0 * X
Z
= Vector3.from_coords(X, Y, Z) mesh_pts
# add noise to the mesh
= Vector3.random((plane_h, plane_w))
rand_pts min=-0.1, max=0.1)
rand_pts.z.clamp_(
= mesh_pts + rand_pts mesh_view: Vector3
= mesh_view.x.ravel().detach().cpu().numpy().tolist()
x_view = mesh_view.y.ravel().detach().cpu().numpy().tolist()
y_view = mesh_view.z.ravel().detach().cpu().numpy().tolist()
z_view = px.scatter_3d(dict(x=x_view, y=y_view, z=z_view, category=["view"] * len(x_view)), "x", "y", "z", color="category")
fig fig.show()
# create rotation
= torch.tensor(3.141616 / 4)
angle_rad = So3.rot_x(angle_rad)
rot_x = So3.rot_z(angle_rad)
rot_z = rot_x * rot_z
rot print(rot)
Parameter containing:
tensor([ 0.8536, 0.3536, -0.1464, 0.3536], requires_grad=True)
# apply the rotation to the mesh points
# TODO: this should work as `rot * mesh_view`
= stack([rot * x for x in mesh_view.view(-1, 3)]).detach()
points_rot = Vector3(points_rot) points_rot
= points_rot.x.ravel().detach().cpu().numpy().tolist()
x_rot = points_rot.y.ravel().detach().cpu().numpy().tolist()
y_rot = points_rot.z.ravel().detach().cpu().numpy().tolist()
z_rot
= px.scatter_3d(
fig dict(
=x_view + x_rot,
x=y_view + y_rot,
y=z_view + z_rot,
z=["view"] * len(x_view) + ["rotated"] * len(x_rot),
category
),"x",
"y",
"z",
="category",
color
) fig.show()
# estimate the plane from the rotated points
= fit_plane(points_rot)
plane_in_ground_fit: Hyperplane print(plane_in_ground_fit)
Normal: x: -0.0002799616486299783
y: 0.7073221206665039
z: -0.7068911790847778
Offset: 0.094654381275177
# project the original points to the estimated plane
= plane_in_ground_fit.projection(mesh_view.view(-1, 3)) points_proj: Vector3
= points_proj.x.ravel().detach().cpu().numpy().tolist()
x_proj = points_proj.y.ravel().detach().cpu().numpy().tolist()
y_proj = points_proj.z.ravel().detach().cpu().numpy().tolist()
z_proj = ["view"] * len(x_view) + ["rotated"] * len(x_rot) + ["projection"] * len(x_proj)
categories = px.scatter_3d(
fig dict(
=x_view + x_rot + x_proj,
x=y_view + y_rot + y_proj,
y=z_view + z_rot + z_proj,
z=categories,
category
),"x",
"y",
"z",
="category",
color
) fig.show()