Modified 2020-11-03 by David Oort Alonso
Apply your competences in software development in a perception pipeline.
The goal of this exercise is to put your skills in computer graphics to the test by projecting a complex 3D model on an AprilTag at an arbitrary position.
Advanced skills on how to manipulate transformations in Computer Graphics.
Insights into the computer graphics pipeline.
Modified 2020-10-31 by Aleksandar Petrov
In this exercise you are asked to render a complete 3D model of a duckie on an image. The duckie model is provided as an .obj
file. Similarly to many augmented reality games the model needs to be projected on an easily recognizable flat pattern. In this exercise you will use an AprilTag for this purpose.
You should have received some traffic signs with AprilTags with the your Duckiebot box. They should look something like:
In Duckietown, AprilTags are recognized and managed through the lib-dt-apriltags Python package. Check it out to see how to use it!
In order to solve the exercise you will have to create a package called augmented_reality_apriltag
with the functionalities specified in Unit A-3 - Basic Augmented Reality Exercise.
Modified 2020-11-03 by David Oort Alonso
This exercise package structure will be based on the one provided by the AprilTag Template. Inside there you will find everything you need like the 3D model and the provided files.
In this exercise you will have to use the AprilTag library so check that it has been added in the dependencies-py3.txt
as dt-apriltags
.
We provided you a file called renderClass.py
. Inside you will find the Renderer
class which allows you to draw a 3D .obj
model onto an image. If you are curious about how this happens, the code inside this file is a modified version of Pygame OBJFileLoader.
The provided Renderer class contains the method render(img, projection_matrix)
, where img
is the image you want to project the model onto and projection_matrix
is the 3x4 matrix that transforms the 3D model coordinates to the AprilTag reference system allowing you to project it.
The constructor of an instance of the Renderer
class requires the 3D model as input. Keep the 3D model in a directory with the path src/models
. You can use the code below to correctly initialize an instance of the Renderer
class:
# Import class from file.
from renderClass import Renderer
rospack = rospkg.RosPack()
# Initialize an instance of Renderer giving the model in input.
self.renderer = Renderer(rospack.get_path('YOUR PACKAGE NAME')+'/src/models/duckie.obj')
Please refrain from changing the renderClass.py
file. It has been tested and any change might lead to unexpected errors and problems that will not be supported.
You will also get a function to load the calibration parameters of your Duckiebot camera which should be in the node python file.
Conversely to the exercise in the previous section, here you are not asked to rectify the image to reduce the delay of this node. You are nonetheless invited to try this yourself and see how accuracy and speed are affected.
Modified 2020-11-03 by David Oort Alonso
Looking at the project as a whole may make it seem more difficult than it really is. But we will follow the latin proverb divide et impera (divide and rule). In other words, we will brake down the big monolithic problem into a few smaller and manageable tasks.
First, let’s focus on what we are trying to achieve: to project a 3D model onto an image such that the position and orientation of the model match the position and orientation of an AprilTag. The break-down of this task looks like that:
Detect the AprilTag and extract its reference frame.
Estimate the homography matrix: determine the transformation from the reference frame of the AprilTag (2D) to the reference frame of the target image (2D). This transformation is the homography matrix. For this step and the previous one, have a look at the lib-dt-apriltags repository, you will find it quite useful.
Derive the transformation from the reference frame of the AprilTag to the target image reference frame: if we want to project a 3D model placed on top of the reference surface to the target image, we need to extend the previous transformation to handle cases were the height of the point to project is different from zero. This can be achieved with some knowledge about coordinate system transformations and a bit of algebra. To know more about homography and orthonormal basis give a look here.
Project our 3D model in the image (pixel space) and draw it: you can use the provided Renderer
class for this. This class has a method called render
which gets an input img
of type InputOutputArray and projection_matrix
(3x4 floating-point matrix). The render
method colors the polygons formed by the vertices of the .obj
file.
The expected outcome of this exercise should something like this:
Modified 2020-10-31 by Aleksandar Petrov
As you might have seen the AprilTag detection adds some delay to the pipeline. However, you can try to change some parameters for a better accuracy and speed trade-off. Try to play around with the parameters nthreads
and quad_decimate
of the dt_apriltags.Detector
class. What do they change? Does the speed improve? What about the stability and accuracy of the detector?