ZMap¶
ZMaps are another representation for 3D data. They are generated by capturing the orthogonal projection of a point cloud or a mesh onto an arbitrary 3D reference plane.
They contain an image in which each pixel value represents a positive distance from the reference plane.
They are grayscale images like depth maps but represent metric and corrected 3D points.
They are convenient representations for measurement and matching.
They are compatible with most 2D processing functions.
An EDepthMap .NET Python and the corresponding EZMap .NET Python. The ZMap is captured from a different reference plane.¶
A ZMap also contains the following information:
The transformation from the World coordinates to the ZMap coordinates.
The size of a pixel, called the resolution.
Hint
Use the method
AsEImage.NET Python to obtain a reference to the contained image. This is useful to use all 2D processing features of eVision on ZMaps.Like in depth maps, a specific pixel value is reserved to represent undefined pixels. To get this pixel value, use the method
GetUndefinedValue.NET Python.These methods are not defined for the base class
EZMap.NET Python but are defined for all subclassesEZMap8.NET Python,EZMap16.NET Python andEZMap32f.NET Python
Generating a ZMap¶
The EPointCloudToZMapConverter .NET Python class implements the conversion from a point cloud to a ZMap (EMeshToZMapConverter .NET Python converts a mesh to a ZMap). With all parameters at default value, the EPointCloudToZMapConverter::Convert .NET Python method automatically chooses the projection plane, the orientation, the map size and the resolution.
Several methods are available to further control the conversion:
EPointCloudToZMapConverter::SetReferencePlane.NET Python defines a world space projection plane. The values of the ZMap pixels are the distance of the point cloud to that reference plane. By default, the reference plane crosses the origin and is perpendicular to the world Z axis. The plane is defined as aE3DPlane.NET Python object.EPointCloudToZMapConverter::SetOrientationVector.NET Python sets a world space vector representing the expected direction of the X (width) axis of the ZMap. The orientation vector allows you to “rotate” the object around the normal of the reference plane.EPointCloudToZMapConverter::SetOrigin.NET Python specifies the world position that is on the ZMap lower left pixel (0, 0).EPointCloudToZMapConverter::SetMapSize.NET Python defines the resolution (number of pixels in X and Y axis) of the generated ZMap.EPointCloudToZMapConverter::SetMapXYResolution.NET Python adjusts the X and Y resolution of the ZMap pixels, in world space unit per pixel (for example mm/pixel). This value is used to compute the ZMap size (width and height), depending on the projected size of the point cloud on the reference plane.EPointCloudToZMapConverter::SetMapZResolution.NET Python sets the Z resolution, in world space unit per pixel unit (gray value). The Z resolution is used to compute the transformation of the distance to the reference plan to the integer 8, 16 or 32 bits pixel value.EPointCloudToZMapConverter::EnableFillMode.NET Python andEPointCloudToZMapConverter::SetFillMode.NET Python control the options used to fill the “hole” in the ZMap. A hole exists when no 3D point is projected in the ZMap at a pixel position.
The methods EPointCloudToZMapConverter::SetReferencePlane .NET Python, EPointCloudToZMapConverter::SetOrientationVector .NET Python and EPointCloudToZMapConverter::SetOrigin .NET Python are used to set up the transformation between the world space and the ZMap space. This transformation is rigid (distances are kept).
Alternatively, it is possible to directly set that transformation with the method EPointCloudToZMapConverter::SetWorldToZMapTransform .NET Python using a rigid matrix as parameter. In that case, the reference plane, the orientation vector and the origin parameters are ignored.
The projection of a point cloud on a ZMap, showing three coordinate systems: the world space, the ZMap space and the pixel space.¶
The EPointCloudToZMapConverter::Convert .NET Python method performs the effective projection of a point cloud (EPointCloud .NET Python) or a 3D object (EMesh .NET Python) to the 8, 16 or 32 bits ZMap.
When generating a ZMap from a point cloud, only individual points are projected on the ZMap. Depending on the point cloud density and the ZMap resolution, some regions of the ZMap may remain “undefined”. To get around this problem, adjust the resolution of the ZMap (EPointCloudToZMapConverter::SetMapXYResolution .NET Python method) to remove “holes” on the ZMap.
By default, the point cloud to ZMap converter performs a filling algorithm. This process tries to replace undefined pixels with locally interpolated values.
As a mesh defines a surface, its triangles are projected onto the ZMap plane. Thus, the generated image shows better continuity and less undefined pixels. However, the generation of a ZMap from an EMesh .NET Python is slower than from an EPointCloud .NET Python.
Creating a Point Cloud from a ZMap¶
To generate a point cloud from a ZMap, use the EZMapToPointCloudConverter .NET Python class.
The EZMapToPointCloudConverter::Convert .NET Pythonmethod takes:
A ZMap source
A
EPointCloud.NET Python destination.4 optional parameters:
An
ERegion.NET Python that defines the domain of the ZMap to convert. By default, uses all the defined pixels of the ZMap generate the point cloud.A parameter to select the world space (by default) or the ZMap space to store the resulting positions in the point cloud.
Whether to compute the normals of the points of the point cloud during the conversion. This is not done by default.
A black and white or color image (with the same size as the ZMap) that is used to generate the intensity or color attribute of the point cloud.
Managing Coordinates¶
Coordinate Systems on a ZMap¶
A ZMap has multiple coordinate systems:
The world space system is the original, metric space from which the ZMap has been generated. Point clouds and meshes are expressed in the world coordinate system.
The ZMap space is defined by a rigid transformation of the world space. The basis linked to this transformation is attached to the lower left corner of the ZMap.
The image space is the system attached to the image representation of the ZMap. Its origin is the upper left corner of the ZMap and its unit length is one pixel along the X and Y axis.
The transformations between:
The image space and the ZMap space include a scale factor.
The ZMap space and the world space are solid transformations.
Transformation from the ZMap coordinate system to the image coordinate system, and vice versa.¶
EZMap¶
The EZMap .NET Python object exposes a set of methods to convert coordinates between world, ZMap and image spaces:
EZMap::ImageToZMap.NET Python converts a 2D position in the image to ZMap coordinates.EZMap::ZMapToImage.NET Python is the reciprocal operation and converts a ZMap position to an image position.EZMap::ZMapToWorld.NET Python is a method to transform positions from the 3D ZMap space to the 3D world space. The world space is the original point cloud or mesh space.EZMap::WorldToZMap.NET Python is the reciprocal operation, converting from world space to ZMap.EZMap::ImageToWorld.NET Python andEZMap::WorldToImage.NET Python combine the functions above to transform directly from image space to world space (or the other way). These methods only perform geometric transformations between the various coordinate systems and do not access the actual ZMap gray scale values.
An overload of EZMap::ImageToWorld .NET Python computes the world point corresponding to a 2D image point without specifying its \(z\) coordinate.
The \(z\) coordinate is taken as the median or mean of the \(z\) coordinates of the pixels in the vicinity of the 2D image point. This is useful to align an object based on features found on the ZMap with 2D operators.
The \(z\) coordinate is computed on the vicinity because the feature itself may not have a defined \(z\) coordinate, for example if it is the center of a hole.
The functions that access the pixel values are:
EZMap::GetWorldPositionFromPixelPosition.NET Python is a method transforming the actual pixel value at integer position (u, v) to the original world space. This method queries the ZMap internal representation to get the pixel value w and transform the pixel space (u, v, w) coordinates to a world space position.EZMap16::GetPixelPositionFromWorldPosition.NET Python is a method to get a pixel value from a world position. The world position is projected on the ZMap and the pixel value is returned. If the world position is outside the ZMap domain, the method returnsFALSE.EZMap::GetWorldPositionFromMapPosition.NET Python is a method to get a 3D world position corresponding to a ZMap 2D coordinate. The world position is in the original point cloud space. If the 2D coordinate is undefined, an exception is thrown.
Leveling a ZMap¶
Sometimes, the reference plane of the ZMap is not set correctly.
To solve this problem, use the method EZMapLeveler::Level .NET Python of the class EZMapLeveler .NET Python to reproject the ZMap on a new reference plane.
To specify the new reference plane, you can either:
Give an
ERegionof points contained in the plane to the methodEZMapLeveler::Level.NET Python. The plane might be shifted so that the leveled ZMap contains all the points of the original one.
An ERegion (composed of 2 ERectangle regions) highlighting the new reference plane¶
Give the normal of the new plane to the ZMap (with argument
projectionDirection). The ZMap plane is computed from the normal and shifted so that the new ZMap contains all the points of the old one.
Hint
A typical way to find the projectionDirection is to use an EPlaneFinder .NET Python to find the biggest plane in the ZMap.
Note
See code snippet: “Performing ZMap Leveling”.
To set the angle of the X and Y axes of the leveled ZMap, use the argument
rotationAngle.
Illustration of EZMapLeveler .NET Python showing the default \(0°\) rotation and the correct \(-23°\) rotation.¶
Size and XYZ Resolution Settings¶
There are several options to handle the size and X, Y or Z resolution of the leveled ZMap:
EPreservationMode.NET Python (through methodsEZMapLeveler::GetPreservationModes.NET Python andEZMapLeveler::SetPreservationModes.NET Python) determines whether the XY resolution, size and/or Z resolution of the input ZMap are preserved.When the XY resolution is preserved, the size of the leveled ZMap is adjusted.
When the size of the ZMap is preserved, the resolution is adjusted.
Note
Note that this may introduce holes in the leveled ZMap.
When both are preserved, the visible contents of the ZMap are adjusted, meaning that some undefined pixels may appear on the edges of the ZMap or the extremities of the object may be cropped.
When the Z resolution is preserved, some data may be impossible to represent if the Z range of the leveled ZMap is bigger than the one of the source ZMap (see next point). Otherwise, the Z resolution is recomputed to use the whole range of the ZMap.
To avoid undesired side-effects, only the XY resolution is preserved by default.
Use
EZMapLeveler::SetPreserveZResolutionFailureHandler.NET Python to choose how to handle data falling outside of the representable range of the ZMap whenEPreservationMode.NET Python is set toEPreservationMode_ZResolution.NET Python. The data may be cropped (the corresponding pixel is undefined), Saturated (the corresponding pixel is white) or an exception is thrown when the problem occurs.
3D Position Settings¶
By default, the leveling does not change the underlying 3D data of the ZMap. The goal is to use the leveling to ease some 2D processing while maintaining the link with the real-world positions of the data.
Alternatively, you can use the method
EZMapLeveler::SetPreserve3DPosition.NET Python to alter that behavior and modify the 3D data of the leveled ZMap. In this mode, thez = 0plane is either:The plane defined by the
ERegionwhen the methodEZMapLeveler::Level.NET Python takes a region as argument.The plane used for the leveling when the method
EZMapLeveler::Level.NET Python takes a projection direction as argument.