SuperimposeMesh
All Classes Files Functions Variables Typedefs Enumerations Enumerator Pages
Superimpose an object

This tutorial introduces the basic steps to superimpose an object, i.e. a mesh, on top of an image by using the SICAD class and its methods.

Just have a look at the following commented, ready-to-go, code snippets!

Default easy-peasy SICAD


View it online.

2 
3 #include <cmath>
4 #include <exception>
5 #include <iostream>
6 
7 #include <glm/gtc/matrix_transform.hpp>
8 
9 #include <opencv2/core/core.hpp>
10 #include <opencv2/imgcodecs/imgcodecs.hpp>
11 #include <opencv2/imgproc/imgproc.hpp>
12 
13 
14 int main()
15 {
16  /**
17  * We want to rendere a single mesh on 1 OpenGL viewport.
18  * The SICAD class can be profitably used to accomplish this!
19  *
20  * We first need some parameters to properly draw the object.
21  * These parameters are the hypothetical intrinsic camera parameters that
22  * would be used, or that is actually used, to take grab the image on which
23  * we want to superimpose the mesh.
24  *
25  * For example, we suppose to have a 320x240 camera with focal length
26  * of 257.34 pixels and exact camera center (principal point) at (160, 120).
27  **/
28  const unsigned int cam_width = 320;
29  const unsigned int cam_height = 240;
30  const float cam_fx = 257.34;
31  const float cam_cx = 160;
32  const float cam_fy = 257.34;
33  const float cam_cy = 120;
34 
35 
36  /**
37  * Next, we need a mesh file!
38  * For example, we may want to superimpose the good ol' fiend of Space
39  * Invader arcade game.
40  * Here, by chance, we have a mesh of it ready to for you!
41  *
42  * To associate a mesh to a particular object the SICAD::ModelPathContainer
43  * comes into play. In this way we can associate a tag to a mesh model and
44  * use it during rendering to assign to it a particular pose (position and
45  * orientation).
46  *
47  * NOTE: supported mesh format are the one provided by the ASSIMP library.
48  * Have a look here: http://assimp.org/main_features_formats.html
49  **/
51  obj.emplace("alien", "./spaceinvader.obj");
52 
53 
54  /**
55  * We create a SICAD object by just passing all the camera parameters.
56  **/
57  SICAD si_cad(obj, cam_width, cam_height, cam_fx, cam_fy, cam_cx, cam_cy);
58 
59 
60  /**
61  * We are close to getting our superimposed mesh!
62  * We now need to choose a pose (position and orientation) to which we
63  * render the Space Invader fiend.
64  * Suppose we want it right in front of us, 10 cm away from the camera.
65  * Note that the OpenGL convention is right handed, expressed in meters,
66  * with the z axis coming out from the screen.
67  * This imply that we want the alien at -0.10 m on the z axis.
68  * As far as the orientation is concerned we want it facing us.
69  * Since we have to pass an axis-angle vector and that all zeros is invalid,
70  * we can just pass any versor with a 0 degree angle.
71  *
72  * We now have to associate the pose with a particular mesh model.
73  * Do you remember that we used "alien" for the Space Invader fiend?
74  * Then we just have to associate a tag to the pose and we are ready to
75  * render!
76  * To do so, we just use Superimpose::ModelPose and
77  * Superimpose::ModelPoseContainer as follows.
78  **/
79  Superimpose::ModelPose obj_pose(7);
80  obj_pose[0] = 0;
81  obj_pose[1] = 0;
82  obj_pose[2] = -0.1;
83  obj_pose[3] = 1;
84  obj_pose[4] = 0;
85  obj_pose[5] = 0;
86  obj_pose[6] = 0;
87 
89  objpose_map.emplace("alien", obj_pose);
90 
91 
92  /**
93  * Finally we trivially set the pose of the camera as follows.
94  *
95  * Q: why don't we have another Superimpose:: object to do this?
96  * W: well...it's under development!
97  **/
98  double cam_x[] = { 0, 0, 0};
99  double cam_o[] = {1.0, 0, 0, 0};
100 
101 
102  /**
103  * It's render time!
104  * We save the output of the render right into a cv::Mat and we can use
105  * the well known OpenCV facilities to do whatever we want with it, for
106  * example write it on the filesystem.
107  **/
108  cv::Mat img;
109  si_cad.superimpose(objpose_map, cam_x, cam_o, img);
110  cv::imwrite("./spaceinvader.jpg", img);
111 
112  return EXIT_SUCCESS;
113 }
std::unordered_map< std::string, std::string > ModelPathContainer
Definition: SICAD.h:33
std::vector< double > ModelPose
Definition: Superimpose.h:23
int main()
A Superimpose derived class to superimpose mesh models on images.
Definition: SICAD.h:30
std::multimap< std::string, ModelPose > ModelPoseContainer
Definition: Superimpose.h:25

If instead you want to provide your own OpenGL shader files the code changes just a tiny bit: you just have to provide two more paramenters to the the SICAD constructor.

Use your own OpenGL shaders in SICAD


View it online.

2 
3 #include <cmath>
4 #include <exception>
5 #include <iostream>
6 
7 #include <glm/gtc/matrix_transform.hpp>
8 
9 #include <opencv2/core/core.hpp>
10 #include <opencv2/imgcodecs/imgcodecs.hpp>
11 #include <opencv2/imgproc/imgproc.hpp>
12 
13 
14 int main()
15 {
16  /**
17  * We want to rendere a single mesh on 1 OpenGL viewport.
18  * The SICAD class can be profitably used to accomplish this!
19  *
20  * We first need some parameters to properly draw the object.
21  * These parameters are the hypothetical intrinsic camera parameters that
22  * would be used, or that is actually used, to take grab the image on which
23  * we want to superimpose the mesh.
24  *
25  * For example, we suppose to have a 320x240 camera with focal length
26  * of 257.34 pixels and exact camera center (principal point) at (160, 120).
27  **/
28  const unsigned int cam_width = 320;
29  const unsigned int cam_height = 240;
30  const float cam_fx = 257.34;
31  const float cam_cx = 160;
32  const float cam_fy = 257.34;
33  const float cam_cy = 120;
34 
35 
36  /**
37  * Next, we need a mesh file!
38  * For example, we may want to superimpose the good ol' fiend of Space
39  * Invader arcade game.
40  * Here, by chance, we have a mesh of it ready to for you!
41  *
42  * To associate a mesh to a particular object the SICAD::ModelPathContainer
43  * comes into play. In this way we can associate a tag to a mesh model and
44  * use it during rendering to assign to it a particular pose (position and
45  * orientation).
46  *
47  * NOTE: supported mesh format are the one provided by the ASSIMP library.
48  * Have a look here: http://assimp.org/main_features_formats.html
49  **/
51  obj.emplace("alien", "./spaceinvader.obj");
52 
53 
54  /**
55  * We create a SICAD object by passing all the camera parameters, the shader
56  * folder path containing the shader code (don't worry, we provide basic
57  * shaders as well!).
58  * Note that for this simple tutorial we assume that the shader files are
59  * (magically) in the same folder of the executable, that's why we use ".".
60  *
61  * Shader code is included at the end of this snippet code. Have a look at
62  * it, it's really simple! If you are not used to it, there are plenty of
63  * tutorials online for writing OpenGL shaders.
64  **/
65  SICAD si_cad(obj, cam_width, cam_height, cam_fx, cam_fy, cam_cx, cam_cy, 1, ".");
66 
67 
68  /**
69  * We are close to getting our superimposed mesh!
70  * We now need to choose a pose (position and orientation) to which we
71  * render the Space Invader fiend.
72  * Suppose we want it right in front of us, 10 cm away from the camera.
73  * Note that the OpenGL convention is right handed, expressed in meters,
74  * with the z axis coming out from the screen.
75  * This imply that we want the alien at -0.10 m on the z axis.
76  * As far as the orientation is concerned we want it facing us.
77  * Since we have to pass an axis-angle vector and that all zeros is invalid,
78  * we can just pass any versor with a 0 degree angle.
79  *
80  * We now have to associate the pose with a particular mesh model.
81  * Do you remember that we used "alien" for the Space Invader fiend?
82  * Then we just have to associate a tag to the pose and we are ready to
83  * render!
84  * To do so, we just use Superimpose::ModelPose and
85  * Superimpose::ModelPoseContainer as follows.
86  **/
87  Superimpose::ModelPose obj_pose(7);
88  obj_pose[0] = 0;
89  obj_pose[1] = 0;
90  obj_pose[2] = -0.1;
91  obj_pose[3] = 1;
92  obj_pose[4] = 0;
93  obj_pose[5] = 0;
94  obj_pose[6] = 0;
95 
97  objpose_map.emplace("alien", obj_pose);
98 
99 
100  /**
101  * Finally we trivially set the pose of the camera as follows.
102  *
103  * Q: why don't we have another Superimpose:: object to do this?
104  * W: well...it's under development!
105  **/
106  double cam_x[] = { 0, 0, 0};
107  double cam_o[] = {1.0, 0, 0, 0};
108 
109 
110  /**
111  * It's render time!
112  * We save the output of the render right into a cv::Mat and we can use
113  * the well known OpenCV facilities to do whatever we want with it, for
114  * example write it on the filesystem.
115  **/
116  cv::Mat img;
117  si_cad.superimpose(objpose_map, cam_x, cam_o, img);
118  cv::imwrite("./spaceinvader.jpg", img);
119 
120  return EXIT_SUCCESS;
121 }
std::unordered_map< std::string, std::string > ModelPathContainer
Definition: SICAD.h:33
std::vector< double > ModelPose
Definition: Superimpose.h:23
A Superimpose derived class to superimpose mesh models on images.
Definition: SICAD.h:30
std::multimap< std::string, ModelPose > ModelPoseContainer
Definition: Superimpose.h:25

Here are the shaders and the Space Invaders mesh model:

⚠️ The four shaders must have the following exact names:

Result + Next


You should get something like this:

alien.jpg
👾

You can now proceed to the next tutorial: how to add a background!