Skip to content

Commit 39af482

Browse files
committed
Merge pull request #1429 from paroj:ovis
2 parents 32fb4b9 + d0964ab commit 39af482

File tree

9 files changed

+1071
-0
lines changed

9 files changed

+1071
-0
lines changed

modules/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ $ cmake -D OPENCV_EXTRA_MODULES_PATH=<opencv_contrib>/modules -D BUILD_opencv_<r
4040

4141
- **optflow**: Optical Flow -- Algorithms for running and evaluating deepflow, simpleflow, sparsetodenseflow and motion templates (silhouette flow).
4242

43+
- **ovis**: OGRE 3D Visualiser -- allows you to render 3D data using the OGRE 3D engine.
44+
4345
- **plot**: Plotting -- The plot module allows you to easily plot data in 1D or 2D.
4446

4547
- **reg**: Image Registration -- Pixels based image registration for precise alignment. Follows the paper "Image Alignment and Stitching: A Tutorial", by Richard Szeliski.

modules/ovis/CMakeLists.txt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
set(the_description "OGRE 3D Visualiser.")
2+
3+
find_package(OGRE 1.10 QUIET)
4+
5+
if(NOT OGRE_FOUND)
6+
message(STATUS "Module opencv_ovis disabled because OGRE3D was not found.")
7+
ocv_module_disable(ovis)
8+
endif()
9+
10+
include_directories(${OGRE_INCLUDE_DIRS}})
11+
link_directories(${OGRE_LIBRARY_DIRS})
12+
13+
ocv_define_module(ovis opencv_core opencv_imgproc opencv_calib3d WRAP python)
14+
ocv_warnings_disable(CMAKE_CXX_FLAGS -Wunused-parameter)
15+
ocv_target_link_libraries(${the_module} ${OGRE_LIBRARIES})

modules/ovis/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
OVIS Module
2+
===========
3+
4+
allows you to render 3D data using the OGRE 3D engine and obtain the rendering as cv::Mat.

modules/ovis/include/opencv2/ovis.hpp

Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
// This file is part of OpenCV project.
2+
// It is subject to the license terms in the LICENSE file found in the top-level directory
3+
// of this distribution and at http://opencv.org/license.html.
4+
5+
#ifndef _OPENCV_OVIS_H_
6+
#define _OPENCV_OVIS_H_
7+
8+
#include <opencv2/core.hpp>
9+
10+
/**
11+
@defgroup ovis OGRE 3D Visualiser
12+
*/
13+
14+
namespace cv {
15+
namespace ovis {
16+
//! @addtogroup ovis
17+
//! @{
18+
19+
enum SceneSettings
20+
{
21+
/// the window will use a seperate scene. The scene will be shared otherwise.
22+
SCENE_SEPERATE = 1,
23+
/// allow the user to control the camera.
24+
SCENE_INTERACTIVE = 2,
25+
/// draw coordinate system crosses for debugging
26+
SCENE_SHOW_CS_CROSS = 4
27+
};
28+
29+
enum MaterialProperty
30+
{
31+
MATERIAL_POINT_SIZE,
32+
MATERIAL_OPACITY,
33+
MATERIAL_EMISSIVE,
34+
MATERIAL_TEXTURE
35+
};
36+
37+
/**
38+
* A 3D viewport and the associated scene
39+
*/
40+
class CV_EXPORTS_W WindowScene {
41+
public:
42+
virtual ~WindowScene();
43+
44+
/**
45+
* set window background to custom image
46+
*
47+
* creates a texture named "<title>_Background"
48+
* @param image
49+
*/
50+
CV_WRAP virtual void setBackground(InputArray image) = 0;
51+
52+
/**
53+
* place an entity of an mesh in the scene
54+
* @param name entity name
55+
* @param meshname mesh name
56+
* @param rot Rodrigues vector or 3x3 rotation matrix
57+
* @param tvec translation
58+
*/
59+
CV_WRAP virtual void createEntity(const String& name, const String& meshname,
60+
InputArray tvec = noArray(), InputArray rot = noArray()) = 0;
61+
62+
/**
63+
* convenience method to visualize a camera position
64+
*
65+
* the entity uses a material with the same name that can be used to change the line color.
66+
* @param name entity name
67+
* @param K intrinsic matrix
68+
* @param imsize image size
69+
* @param zFar far plane in camera coordinates
70+
* @param rot Rodrigues vector or 3x3 rotation matrix
71+
* @param tvec translation
72+
* @return the extents of the Frustum at far plane, where the top left corner denotes the principal
73+
* point offset
74+
*/
75+
CV_WRAP virtual Rect2d createCameraEntity(const String& name, InputArray K, const Size& imsize,
76+
float zFar, InputArray tvec = noArray(),
77+
InputArray rot = noArray()) = 0;
78+
79+
/**
80+
* creates a point light in the scene
81+
* @param name entity name
82+
* @param rot Rodrigues vector or 3x3 rotation matrix
83+
* @param tvec translation
84+
* @param diffuseColor
85+
* @param specularColor
86+
*/
87+
CV_WRAP virtual void createLightEntity(const String& name, InputArray tvec = noArray(),
88+
InputArray rot = noArray(),
89+
const Scalar& diffuseColor = Scalar::all(1),
90+
const Scalar& specularColor = Scalar::all(1)) = 0;
91+
92+
/**
93+
* update entity pose by transformation in the parent coordinate space. (pre-rotation)
94+
* @param name entity name
95+
* @param rot Rodrigues vector or 3x3 rotation matrix
96+
* @param tvec translation
97+
*/
98+
CV_WRAP virtual void updateEntityPose(const String& name, InputArray tvec = noArray(),
99+
InputArray rot = noArray()) = 0;
100+
101+
/**
102+
* set entity pose in the world coordinate space.
103+
* @param name enitity name
104+
* @param rot Rodrigues vector or 3x3 rotation matrix
105+
* @param tvec translation
106+
* @param invert use the inverse of the given pose
107+
*/
108+
CV_WRAP virtual void setEntityPose(const String& name, InputArray tvec = noArray(),
109+
InputArray rot = noArray(), bool invert = false) = 0;
110+
111+
/**
112+
* read back image of last call to @ref renderOneFrame
113+
*/
114+
CV_WRAP virtual void getScreenshot(OutputArray frame) = 0;
115+
116+
/**
117+
* convenience method to force the "up" axis to stay fixed
118+
*
119+
* works with both programmatic changes and SCENE_INTERACTIVE
120+
* @param useFixed whether to enforce the fixed yaw axis
121+
* @param up the axis to be fixed
122+
*/
123+
CV_WRAP virtual void fixCameraYawAxis(bool useFixed, InputArray up = noArray()) = 0;
124+
125+
/**
126+
* Sets the current camera pose
127+
* @param rot Rodrigues vector or 3x3 rotation matrix
128+
* @param tvec translation
129+
* @param invert use the inverse of the given pose
130+
*/
131+
CV_WRAP virtual void setCameraPose(InputArray tvec = noArray(), InputArray rot = noArray(),
132+
bool invert = false) = 0;
133+
134+
/**
135+
* convenience method to orient the camera to a specific entity
136+
* @param target entity name
137+
* @param offset offset from entity centre
138+
*/
139+
CV_WRAP virtual void setCameraLookAt(const String& target, InputArray offset = noArray()) = 0;
140+
141+
/**
142+
* Retrieves the current camera pose
143+
* @param R 3x3 rotation matrix
144+
* @param tvec translation vector
145+
* @param invert return the inverted pose
146+
*/
147+
CV_WRAP virtual void getCameraPose(OutputArray R = noArray(), OutputArray tvec = noArray(),
148+
bool invert = false) = 0;
149+
150+
/**
151+
* set intrinsics of the camera
152+
* @param K intrinsic matrix
153+
* @param imsize image size
154+
*/
155+
CV_WRAP virtual void setCameraIntrinsics(InputArray K, const Size& imsize) = 0;
156+
};
157+
158+
/**
159+
* Add an additional resource location that is search for meshes, textures and materials
160+
*
161+
* must be called before the first createWindow. If give path does not exist, retries inside
162+
* Ogre Media Directory.
163+
* @param path folder or Zip archive.
164+
*/
165+
CV_EXPORTS_W void addResourceLocation(const String& path);
166+
167+
/**
168+
* create a new rendering window/ viewport
169+
* @param title window title
170+
* @param size size of the window
171+
* @param flags @see SceneSettings
172+
*/
173+
CV_EXPORTS_W Ptr<WindowScene> createWindow(const String& title, const Size& size,
174+
int flags = SCENE_INTERACTIVE);
175+
176+
/**
177+
* update all windows
178+
* @return true if this functian can be called again (i.e. continue rendering). false otherwise.
179+
*/
180+
CV_EXPORTS_W bool renderOneFrame();
181+
182+
/**
183+
* set the property of a material to the given value
184+
* @param name material name
185+
* @param prop property @ref MaterialProperty
186+
* @param value the value
187+
*/
188+
CV_EXPORTS_W void setMaterialProperty(const String& name, int prop, const Scalar& value);
189+
190+
/// @overload
191+
CV_EXPORTS_W void setMaterialProperty(const String& name, int prop, const String& value);
192+
193+
/**
194+
* create a 2D plane, X right, Y down, Z up
195+
*
196+
* creates a material and a texture with the same name
197+
* @param name name of the mesh
198+
* @param size size in world units
199+
* @param image optional texture
200+
*/
201+
CV_EXPORTS_W void createPlaneMesh(const String& name, const Size2f& size, InputArray image = noArray());
202+
203+
/**
204+
* creates a point cloud mesh
205+
*
206+
* creates a material with the same name
207+
* @param name name of the mesh
208+
* @param vertices float vector of positions
209+
* @param colors uchar vector of colors
210+
*/
211+
CV_EXPORTS_W void createPointCloudMesh(const String& name, InputArray vertices, InputArray colors = noArray());
212+
213+
/**
214+
* creates a grid
215+
*
216+
* creates a material with the same name
217+
* @param name name of the mesh
218+
* @param size extents of the grid
219+
* @param segments number of segments per side
220+
*/
221+
CV_EXPORTS_W void createGridMesh(const String& name, const Size2f& size, const Size& segments = Size(1, 1));
222+
//! @}
223+
}
224+
}
225+
226+
#endif

modules/ovis/samples/aruco_ar_demo.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import cv2
2+
import numpy as np
3+
4+
# aruco
5+
adict = cv2.aruco.Dictionary_get(cv2.aruco.DICT_4X4_50)
6+
cv2.imshow("marker", cv2.aruco.drawMarker(adict, 0, 400))
7+
8+
# random calibration data. your mileage may vary.
9+
imsize = (800, 600)
10+
K = cv2.getDefaultNewCameraMatrix(np.diag([800, 800, 1]), imsize, True)
11+
12+
# AR scene
13+
cv2.ovis.addResourceLocation("packs/Sinbad.zip") # shipped with Ogre
14+
15+
win = cv2.ovis.createWindow("arucoAR", imsize, flags=0)
16+
win.createEntity("figure", "Sinbad.mesh", (0, 0, -5), (-1.57, 0, 0))
17+
win.createLightEntity("sun", (0, 0, -100))
18+
19+
# video capture
20+
cap = cv2.VideoCapture(0)
21+
cap.set(cv2.CAP_PROP_FRAME_WIDTH, imsize[0])
22+
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, imsize[1])
23+
24+
while cv2.ovis.renderOneFrame():
25+
img = cap.read()[1]
26+
win.setBackground(img)
27+
corners, ids = cv2.aruco.detectMarkers(img, adict)[:2]
28+
29+
cv2.waitKey(1)
30+
31+
if ids is None:
32+
continue
33+
34+
rvecs, tvecs = cv2.aruco.estimatePoseSingleMarkers(corners, 5, K, None)[:2]
35+
win.setCameraPose(tvecs[0].ravel(), rvecs[0].ravel(), invert=True)

modules/ovis/samples/ovis_demo.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import cv2
2+
import numpy as np
3+
4+
# add some external resources
5+
cv2.ovis.addResourceLocation("packs/Sinbad.zip")
6+
7+
# camera intrinsics
8+
imsize = (800, 600)
9+
K = np.diag([800, 800, 1])
10+
K[:2, 2] = (400, 100) # offset pp
11+
12+
# observer scene
13+
owin = cv2.ovis.createWindow("VR", imsize)
14+
cv2.ovis.createGridMesh("ground", (10, 10), (10, 10))
15+
owin.createEntity("ground", "ground", rot=(1.57, 0, 0))
16+
owin.createCameraEntity("cam", K, imsize, 5)
17+
owin.createEntity("figure", "Sinbad.mesh", (0, -5, 0)) # externally defined mesh
18+
owin.createLightEntity("sun", (0, 0, -100))
19+
20+
# interaction scene
21+
iwin = cv2.ovis.createWindow("AR", imsize, cv2.ovis.SCENE_SEPERATE | cv2.ovis.SCENE_INTERACTIVE)
22+
iwin.createEntity("figure", "Sinbad.mesh", (0, -5, 0))
23+
iwin.createLightEntity("sun", (0, 0, -100))
24+
iwin.setCameraIntrinsics(K, imsize)
25+
26+
while cv2.ovis.renderOneFrame():
27+
R, t = iwin.getCameraPose()
28+
owin.setEntityPose("cam", t, R)

0 commit comments

Comments
 (0)