PanoNode
The PanoNode class in Geomapi represents the data and metadata of panoramic Photos, often derived from 3D scanners or spherical cameras. The metadata builds upon the RDFlib framework:
https://rdflib.readthedocs.io/
The code below shows how to create a PanoNode from various inputs.
First the geomapi and external packages are imported
#IMPORT PACKAGES
from rdflib import Graph
import os
import numpy as np
#IMPORT MODULES
from context import geomapi #context import for documentation only
from geomapi.nodes import PanoNode
Jupyter environment detected. Enabling Open3D WebVisualizer.
[Open3D INFO] WebRTC GUI backend enabled.
[Open3D INFO] WebRTCWindowSystem: HTTP handshake server disabled.
PanoNode Creation
A PanoNode is constructed using the same parameters as the base Node. Please refer to Node Tutorial For more info about Node Creation
PanoNode( subject = None, # (URIRef, optional) : A subject to use as identifier for the Node.
graph = None, # (Graph, optional) : An RDF Graph to parse.
graphPath = None, # (Path, optional) : The path of an RDF Graph to parse.
name = None, # (str, optional) : A name of the Node.
path = None, # (Path, optional) : A filepath to a resource.
timestamp = None, # (str, optional) : Timestamp for the node.
resource = None, # (optional) : Resource associated with the node.
cartesianTransform = None, # (np.ndarray, optional) : The (4x4) transformation matrix.
orientedBoundingBox = None, # (o3d.geometry.OrientedBoundingBox, optional) : The oriented bounding box of the node.
convexHull = None, # (o3d.geometry.TriangleMesh, optional) : The convex hull of the node.
loadResource = False, # Load the resource at initialization?
jsonPath = None, # (Path, Optional) : Path to the json file with the Panometadata from Navvis.
imageWidth = None, # (int, Optional) : width of the image in pixels (u). Defaults to 2000pix
imageHeight = None, # (int, Optional) : height of the image in pixels (v). Defaults to 1000pix
depth = None, # (float, Optional) : Average depth of the image in meters. Defaults to 10m
)
Ontology link
The PanoNode has 4 new standard properties that are serialized to the graph:
python name |
predicate |
---|---|
|
|
|
|
|
|
|
|
PanoNode Resource
When creating a Node with a resource, it can be done either directly with the resource, or with the path to the resource.
A resource can be a big piece of data, this is why it is not always wanted to load the whole resource at initialization. This is why the loadResource
parameter is default to False
For more info on specific resources, see the corresponding Node type
Loading The Resource
node = PanoNode(path=r"../../..\tests\testfiles\pano\00000-pano.jpg", loadResource=False)
print("resource before loading:",node.resource)
node.load_resource() # Use specialized node fo each type of resource.
print("resource after loading:",node.resource)
Resource not loaded, but path is defined, call `load_resource()` to access it.
resource before loading: None
resource after loading: [[[238 239 241]
[238 239 241]
[238 239 241]
...
[238 239 241]
[238 239 241]
[238 239 241]]
[[238 239 241]
[238 239 241]
[238 239 241]
...
[238 239 241]
[238 239 241]
[238 239 241]]
[[238 239 241]
[238 239 241]
[238 239 241]
...
[238 239 241]
[238 239 241]
[238 239 241]]
...
[[126 138 138]
[126 138 138]
[126 138 138]
...
[130 142 142]
[130 142 142]
[130 142 142]]
[[126 138 138]
[126 138 138]
[126 138 138]
...
[130 142 142]
[130 142 142]
[130 142 142]]
[[126 138 138]
[126 138 138]
[126 138 138]
...
[130 142 142]
[130 142 142]
[130 142 142]]]
Saving The Resource
A Pano resource can be saved to disk using the save_resource()
function.
Currently supports: .ply, .obj
node = PanoNode(path=r"../../..\tests\testfiles\pano\00000-pano.jpg", loadResource=True)
node.save_resource(directory=r"../../../tests/testfiles/resources", extension=".jpg") # Save the resource to the resourcePath
True
PanoNode Transformation
Since every nod has a cartesian transform, it can be transformed using the node.transform()
function.
The transformation also updates the convexHull
and orientedBoundingBox
.
Furthermore, if the PanoNode has a resource, that resource is also transformed.
node = PanoNode()
print(node.cartesianTransform)
transformation = np.array([[0,0,1,0],[0,1,0,0],[1,0,0,0],[0,0,0,1]])
node.transform(transformation=transformation)
print("applying transformation: (-1)")
print(node.cartesianTransform,"\n")
node = PanoNode()
rotation = np.array([90,0,0]) #eulers in degrees
node.transform(rotation=rotation)
print("applying rotation: (90,0,0)")
print(node.cartesianTransform,"\n")
node = PanoNode()
translation = np.array([1,2,3])
node.transform(translation=translation)
print("applying translation: (1,2,3)")
print(node.cartesianTransform)
[[1. 0. 0. 0.]
[0. 1. 0. 0.]
[0. 0. 1. 0.]
[0. 0. 0. 1.]]
applying transformation: (-1)
[[0. 0. 1. 0.]
[0. 1. 0. 0.]
[1. 0. 0. 0.]
[0. 0. 0. 1.]]
applying rotation: (90,0,0)
[[ 1.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00]
[ 0.000000e+00 6.123234e-17 -1.000000e+00 0.000000e+00]
[ 0.000000e+00 1.000000e+00 6.123234e-17 0.000000e+00]
[ 0.000000e+00 0.000000e+00 0.000000e+00 1.000000e+00]]
applying translation: (1,2,3)
[[1. 0. 0. 1.]
[0. 1. 0. 2.]
[0. 0. 1. 3.]
[0. 0. 0. 1.]]
PanoNode Visualisation
When a PanoNode has a resource, the show()
function displays the Panophoto using PIL
node = PanoNode(path=r"../../..\tests\testfiles\pano\00000-pano.jpg", loadResource=True)
node.show(convertColorspace=False) # The standard node has no resource to display

Further reading
Please refer to the full API documentation of the Node class for more details about the functionality