mirror of
https://github.com/opencv/opencv.git
synced 2026-09-12 13:23:03 -05:00
ptcloud: cv::viz3d OpenGL point-cloud/mesh visualization
This commit is contained in:
@@ -1,10 +1,7 @@
|
||||
set(the_description "High level point cloud and mesh operations")
|
||||
|
||||
set(debug_modules "")
|
||||
if(DEBUG_opencv_ptcloud)
|
||||
list(APPEND debug_modules opencv_highgui)
|
||||
endif()
|
||||
ocv_define_module(ptcloud opencv_geometry opencv_imgproc opencv_features opencv_video ${debug_modules}
|
||||
# viz3d visualization lives here and imports the window + OpenGL context from highgui.
|
||||
ocv_define_module(ptcloud opencv_geometry opencv_imgproc opencv_features opencv_video opencv_flann opencv_highgui
|
||||
WRAP java objc python js
|
||||
)
|
||||
ocv_target_link_libraries(${the_module} ${LAPACK_LIBRARIES})
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "opencv2/ptcloud/odometry_frame.hpp"
|
||||
#include "opencv2/ptcloud/odometry_settings.hpp"
|
||||
#include "opencv2/ptcloud/slam.hpp"
|
||||
#include "opencv2/ptcloud/viz3d.hpp"
|
||||
|
||||
/**
|
||||
@defgroup ptcloud Point Cloud Processing
|
||||
|
||||
188
modules/ptcloud/include/opencv2/ptcloud/viz3d.hpp
Normal file
188
modules/ptcloud/include/opencv2/ptcloud/viz3d.hpp
Normal file
@@ -0,0 +1,188 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#ifndef OPENCV_PTCLOUD_VIZ3D_HPP
|
||||
#define OPENCV_PTCLOUD_VIZ3D_HPP
|
||||
|
||||
#include "opencv2/core.hpp"
|
||||
|
||||
namespace cv { namespace viz3d {
|
||||
|
||||
//! Render modes for cv::viz3d::showBox / cv::viz3d::showPlane / cv::viz3d::showSphere
|
||||
enum RenderMode
|
||||
{
|
||||
RENDER_SIMPLE = 0,
|
||||
RENDER_SHADING = 1,
|
||||
RENDER_WIREFRAME = 2,
|
||||
};
|
||||
|
||||
/** @brief Sets the view's perspective on a viz3d window.
|
||||
@param win_name Name of the viz3d window.
|
||||
@param fov Vertical field of view in radians.
|
||||
@param z_near Minimum clip distance.
|
||||
@param z_far Maximum clip distance.
|
||||
*/
|
||||
CV_EXPORTS_W void setPerspective(const String& win_name, float fov, float z_near, float z_far);
|
||||
|
||||
/** @brief Hides or shows the grid on a viz3d window.
|
||||
@param win_name Name of the viz3d window.
|
||||
@param visible Should the grid be shown?
|
||||
*/
|
||||
CV_EXPORTS_W void setGridVisible(const String& win_name, bool visible);
|
||||
|
||||
/** @brief Sets the properties of the light used on a viz3d window.
|
||||
@param win_name Name of the viz3d window.
|
||||
@param direction Direction any point to the sun.
|
||||
@param ambient Ambient light color.
|
||||
@param diffuse Diffuse light color.
|
||||
*/
|
||||
CV_EXPORTS_W void setSun(const String& win_name, const Vec3f& direction, const Vec3f& ambient, const Vec3f& diffuse);
|
||||
|
||||
/** @brief Sets the properties of the sky used on a viz3d window.
|
||||
@param win_name Name of the viz3d window.
|
||||
@param color Sky color.
|
||||
*/
|
||||
CV_EXPORTS_W void setSky(const String& win_name, const Vec3f& color);
|
||||
|
||||
/** @brief Shows a box object in the specified viz3d window. See cv::viz3d::destroyObject.
|
||||
|
||||
@param win_name Name of the viz3d window.
|
||||
@param obj_name Name of the object.
|
||||
@param size Box size.
|
||||
@param color Box color.
|
||||
@param mode Render mode.
|
||||
*/
|
||||
CV_EXPORTS_W void showBox(const String& win_name, const String& obj_name, const Vec3f& size, const Vec3f& color, RenderMode mode = RENDER_SIMPLE);
|
||||
|
||||
/** @brief Shows a plane object in the specified viz3d window. See cv::viz3d::destroyObject.
|
||||
|
||||
The place faces the positive Y axis by default.
|
||||
|
||||
@param win_name Name of the viz3d window.
|
||||
@param obj_name Name of the object.
|
||||
@param size Plane size.
|
||||
@param color Plane color.
|
||||
@param mode Render mode.
|
||||
*/
|
||||
CV_EXPORTS_W void showPlane(const String& win_name, const String& obj_name, const Vec2f& size, const Vec3f& color, RenderMode mode = RENDER_SIMPLE);
|
||||
|
||||
/** @brief Shows a sphere object in the specified viz3d window. See cv::viz3d::destroyObject.
|
||||
|
||||
@param win_name Name of the viz3d window.
|
||||
@param obj_name Name of the object.
|
||||
@param radius Sphere radius.
|
||||
@param color Sphere color.
|
||||
@param mode Render mode.
|
||||
@param divs The higher this integer is the more detail (triangles) the sphere has.
|
||||
*/
|
||||
CV_EXPORTS_W void showSphere(const String& win_name, const String& obj_name, float radius, const Vec3f& color, RenderMode mode = RENDER_SIMPLE, int divs = 3);
|
||||
|
||||
/** @brief Shows a camera trajectory object in the specified viz3d window. See cv::viz3d::destroyObject.
|
||||
|
||||
The camera trajectory data array must be 2D. Each row has a width of 6, where the first
|
||||
3 components are the position and the second 3 components are the direction of the camera.
|
||||
|
||||
@param win_name Name of the viz3d window.
|
||||
@param obj_name Name of the object.
|
||||
@param trajectory Camera trajectory data.
|
||||
@param aspect Aspect ratio of the camera frustum.
|
||||
@param scale Scale applied to camera frustums.
|
||||
@param frustum_color Color of the frustums.
|
||||
@param line_color Color of the line.
|
||||
*/
|
||||
// Not CV_EXPORTS_W: the auto-bindings generator mishandles the two trailing
|
||||
// Vec3f defaults (like the other Vec3f-taking viz3d functions, it stays C++-only).
|
||||
CV_EXPORTS void showCameraTrajectory(
|
||||
const String& win_name, const String& obj_name, InputArray trajectory,
|
||||
float aspect, float scale, Vec3f frustum_color = Vec3f(1.0f, 1.0f, 1.0f),
|
||||
Vec3f line_color = Vec3f(0.5f, 0.5f, 0.5f));
|
||||
|
||||
/** @brief Shows a mesh object in the specified viz3d window. See cv::viz3d::destroyObject.
|
||||
|
||||
The vertices array must be 2D. If shading is disabled (the default option), each row has a width of
|
||||
3 (xyz), 6 (xyz, rgb) or 9 (xyz, rgb, uvw) where uvw is the normal, so that each row represents a vertex.
|
||||
Shading is only enabled when using normals.
|
||||
|
||||
@param win_name Name of the viz3d window.
|
||||
@param obj_name Name of the object.
|
||||
@param verts Vertices input array.
|
||||
@param indices Indices input array.
|
||||
*/
|
||||
CV_EXPORTS void showMesh(const String& win_name, const String& obj_name, InputArray verts, InputArray indices);
|
||||
|
||||
/** @overload Shows a mesh object in the specified viz3d window. See cv::viz3d::destroyObject.
|
||||
|
||||
The vertices array must be 2D, where each row has a width of 3 (xyz), 6 (xyz, rgb) or 9 (xyz, rgb, uvw)
|
||||
where uvw is the normal, so that each row represents a vertex. Shading is only enabled when using normals.
|
||||
Points are grouped in triplets to make triangles (points 1, 2 and 3, points 4, 5 and 6, etc).
|
||||
|
||||
@param win_name Name of the viz3d window.
|
||||
@param obj_name Name of the object.
|
||||
@param verts Vertices input array.
|
||||
@param indices Indices input array.
|
||||
*/
|
||||
CV_EXPORTS_AS(showMesh2) void showMesh(const String& win_name, const String& obj_name, InputArray verts);
|
||||
|
||||
/** @brief Shows a point cloud object in the specified viz3d window. See cv::viz3d::destroyObject.
|
||||
|
||||
The points array must be 2D, where each row has either a width of 6 (xyz, rgb), so that
|
||||
each row represents a point.
|
||||
|
||||
@param win_name Name of the viz3d window.
|
||||
@param obj_name Name of the object.
|
||||
@param points Vertices input array.
|
||||
*/
|
||||
CV_EXPORTS_W void showPoints(const String& win_name, const String& obj_name, InputArray points);
|
||||
|
||||
/** @brief Shows a colored depth map as a point cloud in the specified viz3d window. See cv::viz3d::destroyObject.
|
||||
|
||||
The colored depth map must be a 2D image with 4 channels (RGBD). The points are created assuming
|
||||
that positive depth means positive position in the Z axis.
|
||||
|
||||
@param win_name Name of the viz3d window.
|
||||
@param obj_name Name of the object.
|
||||
@param img Input colored depth map.
|
||||
@param intrinsics Camera intrinsics matrix.
|
||||
@param scale Scale applied to the coordinates of the points.
|
||||
*/
|
||||
CV_EXPORTS_W void showRGBD(const String& win_name, const String& obj_name, InputArray img, const Matx33f& intrinsics, float scale = 1.0f);
|
||||
|
||||
/** @brief Shows a lines object in the specified viz3d window. See cv::viz3d::destroyObject.
|
||||
|
||||
The points array must be 2D, where each row has either a width of 6 (xyz, rgb), so that
|
||||
each row represents a point. Points are grouped in pairs to make lines (points 1 and 2,
|
||||
points 3 and 4, etc).
|
||||
|
||||
@param win_name Name of the viz3d window.
|
||||
@param obj_name Name of the object.
|
||||
@param points Vertices input array.
|
||||
*/
|
||||
CV_EXPORTS_W void showLines(const String& win_name, const String& obj_name, InputArray points);
|
||||
|
||||
/** @brief Sets an object's position in the specified viz3d window.
|
||||
@param win_name Name of the viz3d window.
|
||||
@param obj_name Name of the object.
|
||||
@param position New position.
|
||||
*/
|
||||
CV_EXPORTS_W void setObjectPosition(const String& win_name, const String& obj_name, const Vec3f& position);
|
||||
|
||||
/** @brief Sets an object's rotation in the specified viz3d window.
|
||||
@param win_name Name of the viz3d window.
|
||||
@param obj_name Name of the object.
|
||||
@param rotation New rotation in euler angles (radians).
|
||||
*/
|
||||
CV_EXPORTS_W void setObjectRotation(const String& win_name, const String& obj_name, const Vec3f& rotation);
|
||||
|
||||
/** @brief Destroys an object created with cv::viz3d::showMesh or cv::viz3d::showPoints.
|
||||
|
||||
@param win_name Name of the viz3d window.
|
||||
@param obj_name Name of the object.
|
||||
*/
|
||||
CV_EXPORTS_W void destroyObject(const String& win_name, const String& obj_name);
|
||||
|
||||
} // namespace viz3d
|
||||
} // namespace cv
|
||||
|
||||
|
||||
#endif
|
||||
156
modules/ptcloud/samples/viz3d.cpp
Normal file
156
modules/ptcloud/samples/viz3d.cpp
Normal file
@@ -0,0 +1,156 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include <fstream>
|
||||
#include <opencv2/core.hpp>
|
||||
#include <opencv2/highgui.hpp>
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include <opencv2/ptcloud.hpp> // cv::viz3d now lives in the ptcloud module
|
||||
|
||||
using namespace cv;
|
||||
|
||||
Mat loadPoints(const String& path)
|
||||
{
|
||||
Mat points;
|
||||
std::ifstream ifs(path);
|
||||
|
||||
int _;
|
||||
float x, y, z, r, g, b;
|
||||
Vec3f c = Vec3f::all(0.0f);
|
||||
int count;
|
||||
|
||||
std::string str;
|
||||
std::getline(ifs, str);
|
||||
|
||||
for (count = 0; ifs >> _ && ifs >> x && ifs >> z && ifs >> y && ifs >> r && ifs >> g && ifs >> b; ++count)
|
||||
{
|
||||
y = -y;
|
||||
float data[] = { x, y, z, r / 255.0f, g / 255.0f, b / 255.0f };
|
||||
points.push_back(Mat(Size(6, 1), CV_32F, &data));
|
||||
c += Vec3f(x, y, z);
|
||||
}
|
||||
|
||||
c /= count;
|
||||
|
||||
for (int i = 0; i < count; ++i)
|
||||
for (int j = 0; j < 3; ++j)
|
||||
points.at<float>(i, j) -= c(j);
|
||||
|
||||
return points;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
float verts_data[] = {
|
||||
-0.5, -0.5, 0.0,
|
||||
-0.5, +0.5, 0.0,
|
||||
+0.5, +0.5, 0.0,
|
||||
+0.5, -0.5, 0.0,
|
||||
};
|
||||
|
||||
Mat verts_mat = Mat(Size(3, 4), CV_32F, &verts_data);
|
||||
|
||||
int indices_data[] = {
|
||||
0, 1, 2,
|
||||
2, 3, 0,
|
||||
};
|
||||
|
||||
Mat indices_mat = Mat(Size(3, 2), CV_32S, &indices_data);
|
||||
|
||||
float point_data[] = {
|
||||
-0.5, -0.5, 0.0, 1.0f, 0.0f, 0.0f,
|
||||
-0.5, +0.5, 0.0, 0.0f, 1.0f, 0.0f,
|
||||
+0.5, +0.5, 0.0, 0.0f, 0.0f, 1.0f,
|
||||
+0.5, -0.5, 0.0, 1.0f, 1.0f, 1.0f,
|
||||
};
|
||||
|
||||
Mat points_mat = Mat(Size(6, 4), CV_32F, &point_data);
|
||||
|
||||
float trajectory_data[] = {
|
||||
-0.0, +5.0, +0.0, -1.0f, -1.0f, -1.0f,
|
||||
-5.0, +4.0, +2.0, +0.0f, +0.0f, -1.0f,
|
||||
-10.0, +3.0, +5.0, -0.5f, +0.2f, -0.5f,
|
||||
};
|
||||
|
||||
Mat trajectory_mat = Mat(Size(6, 3), CV_32F, &trajectory_data);
|
||||
|
||||
// Images taken from https://rgbd-dataset.cs.washington.edu
|
||||
// Papers that need to be cited to use this data:
|
||||
// [1] N. Silberman, D. Hoiem, P. Kohli, R. Fergus. Indoor segmentation and support inference from rgbd images. In ECCV, 2012.
|
||||
// [2] A.Janoch, S.Karayev, Y.Jia, J.T.Barron, M.Fritz, K.Saenko, and T.Darrell.A category - level 3 - d object dataset : Putting the kinect to work.In ICCV Workshop on Consumer Depth Cameras for Computer Vision, 2011.
|
||||
// [3] J.Xiao, A.Owens, and A.Torralba.SUN3D : A database of big spaces reconstructed using SfMand object labels.In ICCV, 2013
|
||||
Mat rgbd_components[] = {
|
||||
imread(samples::findFile("rgbd-color.jpg"), IMREAD_COLOR),
|
||||
imread(samples::findFile("rgbd-depth.png"), IMREAD_ANYDEPTH | IMREAD_ANYCOLOR)
|
||||
};
|
||||
|
||||
rgbd_components[0].convertTo(rgbd_components[0], CV_32F);
|
||||
rgbd_components[1].convertTo(rgbd_components[1], CV_32F);
|
||||
|
||||
Mat rgbd;
|
||||
merge(rgbd_components, 2, rgbd);
|
||||
cvtColor(rgbd, rgbd, COLOR_BGRA2RGBA);
|
||||
|
||||
// Point cloud data taken from https://sketchfab.com/3d-models/anthidium-forcipatum-point-cloud-3493da15a8db4f34929fc38d9d0fcb2c
|
||||
Mat bee_mat = loadPoints(samples::findFile("anthidium-forcipatum.csv"));
|
||||
|
||||
// Show two instances of the same example mesh
|
||||
viz3d::showMesh("viz3d", "mesh1", verts_mat, indices_mat);
|
||||
viz3d::showMesh("viz3d", "mesh2", verts_mat, indices_mat);
|
||||
viz3d::setObjectPosition("viz3d", "mesh1", { -2.0f, 0.0f, 0.0f });
|
||||
viz3d::setObjectPosition("viz3d", "mesh2", { 2.0f, 0.0f, 0.0f });
|
||||
|
||||
// Show an example point cloud
|
||||
viz3d::showPoints("viz3d", "points", points_mat);
|
||||
|
||||
// Show a bee point cloud
|
||||
viz3d::showPoints("viz3d", "bee", bee_mat);
|
||||
viz3d::setObjectPosition("viz3d", "bee", { 0.0f, 0.0f, 5.0f });
|
||||
|
||||
// Show RGBD image as points
|
||||
viz3d::showRGBD("rgbd", "rgbd", rgbd, {
|
||||
529.5f, 0.0f, 365.0f,
|
||||
0.0f, 529.5f, 265.0f,
|
||||
0.0f, 0.0f, 1.0f
|
||||
}, 0.1f);
|
||||
viz3d::setObjectPosition("rgbd", "rgbd", { 0.0f, 0.0f, 0.0f });
|
||||
viz3d::setGridVisible("rgbd", true);
|
||||
|
||||
// Show a solid box
|
||||
viz3d::showBox("viz3d", "box1", { 0.25f, 0.25f, 0.25f }, { 0.5f, 1.0f, 0.5f });
|
||||
viz3d::setObjectPosition("viz3d", "box1", { -5.0f, 0.0f, -5.0f });
|
||||
|
||||
// Show 3 wireframe boxes
|
||||
viz3d::showBox("viz3d", "box2", { 1.0f, 0.5f, 0.5f }, { 1.0f, 0.5f, 0.5f }, viz3d::RENDER_SIMPLE);
|
||||
viz3d::showBox("viz3d", "box3", { 0.5f, 1.0f, 0.5f }, { 0.5f, 1.0f, 0.5f }, viz3d::RENDER_WIREFRAME);
|
||||
viz3d::showBox("viz3d", "box4", { 0.5f, 0.5f, 1.0f }, { 0.5f, 0.5f, 1.0f}, viz3d::RENDER_SHADING);
|
||||
viz3d::setObjectPosition("viz3d", "box2", { 5.0f, 0.0f, 5.0f });
|
||||
viz3d::setObjectPosition("viz3d", "box3", { -5.0f, 0.0f, 5.0f });
|
||||
viz3d::setObjectPosition("viz3d", "box4", { -5.0f, 0.0f, 0.0f });
|
||||
|
||||
// Show a solid sphere
|
||||
viz3d::showSphere("viz3d", "sphere1", 1.0f, { 0.7f, 0.9f, 0.7f }, viz3d::RENDER_SHADING);
|
||||
viz3d::setObjectPosition("viz3d", "sphere1", { 0.0f, 0.0f, -5.0f });
|
||||
|
||||
// Show wireframe sphere
|
||||
viz3d::showSphere("viz3d", "sphere2", 1.0f, { 0.7f, 0.9f, 0.7f }, viz3d::RENDER_WIREFRAME);
|
||||
viz3d::setObjectPosition("viz3d", "sphere2", { 5.0f, 0.0f, 0.0f });
|
||||
|
||||
// Show plane
|
||||
viz3d::showPlane("viz3d", "plane1", { 1.5f, 1.0f }, { 0.8f, 0.5f, 0.3f });
|
||||
viz3d::setObjectPosition("viz3d", "plane1", { 5.0f, 0.0f, -5.0f });
|
||||
|
||||
viz3d::showCameraTrajectory("viz3d", "trajectory", trajectory_mat, 1.5f, 0.2f);
|
||||
|
||||
float x = 0.0f;
|
||||
while (waitKey(16) != 27)
|
||||
{
|
||||
// Animate objects
|
||||
viz3d::setObjectRotation("viz3d", "mesh1", { x, 0.0f, 0.0f });
|
||||
viz3d::setObjectRotation("viz3d", "mesh2", { 0.0f, 0.0f, x });
|
||||
x += 0.01f;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
25
modules/ptcloud/src/viz3d/grid_ticks.hpp
Normal file
25
modules/ptcloud/src/viz3d/grid_ticks.hpp
Normal file
@@ -0,0 +1,25 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#ifndef OPENCV_PTCLOUD_VIZ3D_GRID_TICKS_HPP
|
||||
#define OPENCV_PTCLOUD_VIZ3D_GRID_TICKS_HPP
|
||||
|
||||
namespace cv { namespace viz3d { namespace detail {
|
||||
|
||||
// Grid line spacing, snapped so dist_scale / tick_step stays in [2, 4].
|
||||
// Pure math (no OpenGL) so it is unit-testable headless. Terminates for any
|
||||
// finite dist_scale (regression guard for the old logf(1.0)=0 -> inf hang).
|
||||
inline float gridTickStep(float dist_scale)
|
||||
{
|
||||
float tick_step = 1.0f;
|
||||
while (dist_scale / tick_step > 4.0f)
|
||||
tick_step *= 2.0f;
|
||||
while (tick_step > 1e-6f && dist_scale / tick_step < 2.0f)
|
||||
tick_step *= 0.5f;
|
||||
return tick_step;
|
||||
}
|
||||
|
||||
}}} // namespace cv::viz3d::detail
|
||||
|
||||
#endif
|
||||
1592
modules/ptcloud/src/viz3d/viz3d.cpp
Normal file
1592
modules/ptcloud/src/viz3d/viz3d.cpp
Normal file
File diff suppressed because it is too large
Load Diff
209
modules/ptcloud/src/viz3d/viz3d_private.hpp
Normal file
209
modules/ptcloud/src/viz3d/viz3d_private.hpp
Normal file
@@ -0,0 +1,209 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#ifndef OPENCV_PTCLOUD_VIZ3D_PRIVATE_HPP
|
||||
#define OPENCV_PTCLOUD_VIZ3D_PRIVATE_HPP
|
||||
|
||||
#include "../precomp.hpp"
|
||||
#include "opencv2/core/private.hpp" // HAVE_OPENGL from cvconfig.h
|
||||
#include "opencv2/core/opengl.hpp"
|
||||
#include "opencv2/highgui.hpp" // window + OpenGL context (imported from highgui)
|
||||
#include "opencv2/ptcloud/viz3d.hpp" // public viz3d API declarations
|
||||
|
||||
#include <map>
|
||||
|
||||
#ifdef HAVE_OPENGL
|
||||
|
||||
namespace cv { namespace viz3d {
|
||||
|
||||
// Stores a view's matrices
|
||||
class View
|
||||
{
|
||||
public:
|
||||
View();
|
||||
|
||||
void setAspect(float aspect);
|
||||
void setPerspective(float fov, float z_near, float z_far);
|
||||
|
||||
void rotate(float dx, float dy); // Rotates the camera using mouse input
|
||||
void move(float dx, float dy); // Moves the camera using mouse input
|
||||
void scaleDistance(float amount);
|
||||
|
||||
inline Vec3f getOrigin() const { return this->origin; }
|
||||
inline Vec3f getPosition() const { return this->position; }
|
||||
inline float getDistance() const { return this->distance; }
|
||||
inline Matx44f getView() const { return this->view; }
|
||||
inline Matx44f getProj() const { return this->proj; }
|
||||
|
||||
private:
|
||||
void lookAt(const Vec3f& point, const Vec3f& up);
|
||||
|
||||
float aspect;
|
||||
float fov;
|
||||
float z_near;
|
||||
float z_far;
|
||||
|
||||
Matx44f proj;
|
||||
Matx44f view;
|
||||
|
||||
Vec3f origin;
|
||||
Vec3f position;
|
||||
Vec3f up;
|
||||
float distance;
|
||||
};
|
||||
|
||||
// Stores information about a light
|
||||
struct Light
|
||||
{
|
||||
Vec3f direction;
|
||||
Vec3f ambient;
|
||||
Vec3f diffuse;
|
||||
};
|
||||
|
||||
// Base class for viz3d objects which can be rendered
|
||||
class Object
|
||||
{
|
||||
public:
|
||||
Object();
|
||||
virtual ~Object() = default;
|
||||
|
||||
void setPosition(const Vec3f& position);
|
||||
void setRotation(const Vec3f& rotation);
|
||||
|
||||
virtual void draw(const View& view, const Light& light) = 0;
|
||||
|
||||
virtual String getShaderName() = 0;
|
||||
virtual ogl::Program buildShader() = 0;
|
||||
virtual void setShader(ogl::Program program) = 0;
|
||||
|
||||
inline Matx44f getModel() const { return this->model; }
|
||||
|
||||
private:
|
||||
void updateModel();
|
||||
|
||||
Vec3f position;
|
||||
Vec3f rotation;
|
||||
|
||||
Matx44f model;
|
||||
};
|
||||
|
||||
// Class which stores the viz3d data associated to a window.
|
||||
class Window
|
||||
{
|
||||
public:
|
||||
Window(const String& name);
|
||||
~Window();
|
||||
|
||||
Object* get(const String& obj_name);
|
||||
void set(const String& obj_name, Object* obj);
|
||||
|
||||
void setSun(const Vec3f& direction, const Vec3f& ambient, const Vec3f& diffuse);
|
||||
void setSky(const Vec3f& color);
|
||||
void setGridVisible(bool visible);
|
||||
|
||||
void draw();
|
||||
void onMouse(int event, int x, int y, int flags);
|
||||
|
||||
inline View& getView() { return this->view; }
|
||||
|
||||
private:
|
||||
String name;
|
||||
Size size;
|
||||
|
||||
Light sun;
|
||||
Vec3f sky_color;
|
||||
|
||||
View view;
|
||||
int l_mouse_x;
|
||||
int l_mouse_y;
|
||||
|
||||
Object* crosshair;
|
||||
Object* grid;
|
||||
std::map<String, Object*> objects;
|
||||
std::map<String, ogl::Program> shaders;
|
||||
};
|
||||
|
||||
// Class which stores the viz3d data associated to a mesh object.
|
||||
class Mesh : public Object
|
||||
{
|
||||
public:
|
||||
Mesh(InputArray verts, InputArray indices);
|
||||
Mesh(InputArray verts);
|
||||
|
||||
virtual void draw(const View& view, const Light& light) override;
|
||||
|
||||
virtual String getShaderName() override;
|
||||
virtual ogl::Program buildShader() override;
|
||||
virtual void setShader(ogl::Program program) override;
|
||||
|
||||
private:
|
||||
void initVA(int width);
|
||||
|
||||
ogl::Program program;
|
||||
ogl::VertexArray va;
|
||||
ogl::Buffer verts;
|
||||
ogl::Buffer indices;
|
||||
|
||||
int index_type;
|
||||
|
||||
int model_loc;
|
||||
int view_loc;
|
||||
int proj_loc;
|
||||
int sun_direction_loc;
|
||||
int sun_ambient_loc;
|
||||
int sun_diffuse_loc;
|
||||
};
|
||||
|
||||
// Class which stores the viz3d data associated to a lines object.
|
||||
class Lines : public Object
|
||||
{
|
||||
public:
|
||||
Lines(InputArray points, int count = -1);
|
||||
|
||||
virtual void draw(const View& view, const Light& light) override;
|
||||
void update(InputArray points);
|
||||
|
||||
virtual String getShaderName() override;
|
||||
virtual ogl::Program buildShader() override;
|
||||
virtual void setShader(ogl::Program program) override;
|
||||
|
||||
private:
|
||||
ogl::Program program;
|
||||
ogl::VertexArray va;
|
||||
ogl::Buffer points;
|
||||
|
||||
int model_loc;
|
||||
int view_loc;
|
||||
int proj_loc;
|
||||
|
||||
int count;
|
||||
};
|
||||
|
||||
// Data necessary for drawing a point cloud on a window.
|
||||
class PointCloud : public Object
|
||||
{
|
||||
public:
|
||||
PointCloud(InputArray points);
|
||||
|
||||
virtual void draw(const View& view, const Light& light) override;
|
||||
|
||||
virtual String getShaderName() override;
|
||||
virtual ogl::Program buildShader() override;
|
||||
virtual void setShader(ogl::Program program) override;
|
||||
|
||||
private:
|
||||
ogl::Program program;
|
||||
ogl::VertexArray va;
|
||||
ogl::Buffer points;
|
||||
|
||||
int model_loc;
|
||||
int view_loc;
|
||||
int proj_loc;
|
||||
};
|
||||
|
||||
}} // namespace cv::viz3d
|
||||
|
||||
#endif // HAVE_OPENGL
|
||||
|
||||
#endif
|
||||
82
modules/ptcloud/test/test_viz3d.cpp
Normal file
82
modules/ptcloud/test/test_viz3d.cpp
Normal file
@@ -0,0 +1,82 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
#include <opencv2/highgui.hpp> // updateWindow / destroyWindow
|
||||
#include "../src/viz3d/grid_ticks.hpp" // GL-free grid spacing helper
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
using namespace cv;
|
||||
|
||||
// Regression for the grid tick_step infinite-loop hang (#1): the old code did
|
||||
// logf(1.0) == 0 -> division -> inf -> the halving loop never terminated for
|
||||
// distance*scale > 4. gridTickStep must terminate and stay finite/positive for
|
||||
// every distance, including the region that used to hang. GL-free (runs in CI).
|
||||
TEST(Viz3D, grid_tick_step)
|
||||
{
|
||||
// Values span below/at/above the old hang threshold (dist_scale > 4).
|
||||
const float samples[] = { 0.03f, 0.9f, 3.0f, 4.0f, 5.0f, 13.4f, 40.0f, 400.0f, 4000.0f };
|
||||
for (float ds : samples)
|
||||
{
|
||||
float ts = viz3d::detail::gridTickStep(ds);
|
||||
ASSERT_TRUE(std::isfinite(ts)) << "ds=" << ds;
|
||||
ASSERT_GT(ts, 0.0f) << "ds=" << ds;
|
||||
float ratio = ds / ts;
|
||||
EXPECT_GE(ratio, 2.0f - 1e-3f) << "ds=" << ds << " ratio=" << ratio;
|
||||
EXPECT_LE(ratio, 4.0f + 1e-3f) << "ds=" << ds << " ratio=" << ratio;
|
||||
}
|
||||
}
|
||||
|
||||
// viz3d is OpenGL/window based. Skip when no GL context can be created
|
||||
// (e.g. headless CI without a display).
|
||||
static bool viz3dAvailable()
|
||||
{
|
||||
try
|
||||
{
|
||||
viz3d::showPoints("viz3d_gl_probe", "p", Mat::zeros(4, 6, CV_32F));
|
||||
destroyWindow("viz3d_gl_probe");
|
||||
return true;
|
||||
}
|
||||
catch (const cv::Exception&)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Smoke test for the public viz3d API. Builds a scene and forces redraws; passes
|
||||
// if nothing throws. Exercises the paths touched by review fixes: #3 (showRGBD),
|
||||
// #4 (degenerate up-vector trajectory), and the grid render path. The #1 hang
|
||||
// itself is distance-triggered (no public camera-distance setter) and is covered
|
||||
// by the GL-free Viz3D.grid_tick_step test above.
|
||||
TEST(Viz3D, render_scene_smoke)
|
||||
{
|
||||
if (!viz3dAvailable())
|
||||
throw cvtest::SkipTestException("viz3d/OpenGL not available (no GL context)");
|
||||
|
||||
const String w = "viz3d_test";
|
||||
|
||||
Mat pts(256, 6, CV_32F);
|
||||
randu(pts, 0.0f, 1.0f);
|
||||
EXPECT_NO_THROW(viz3d::showPoints(w, "pts", pts));
|
||||
EXPECT_NO_THROW(viz3d::setGridVisible(w, true));
|
||||
|
||||
EXPECT_NO_THROW(viz3d::showBox(w, "box", Vec3f::all(1.0f), Vec3f(1, 0, 0)));
|
||||
EXPECT_NO_THROW(viz3d::showSphere(w, "sphere", 1.0f, Vec3f(0, 1, 0)));
|
||||
|
||||
// forward = (0,+1,0) and (0,-1,0): the degenerate up-vector case guarded by #4.
|
||||
float traj[] = { 0,0,0, 0,1,0, 1,0,0, 0,-1,0 };
|
||||
EXPECT_NO_THROW(viz3d::showCameraTrajectory(w, "traj", Mat(2, 6, CV_32F, traj), 1.0f, 0.5f));
|
||||
|
||||
Mat rgbd(16, 16, CV_32FC4, Scalar(120, 120, 120, 500)); // #3 showRGBD path
|
||||
EXPECT_NO_THROW(viz3d::showRGBD(w, "rgbd", rgbd, Matx33f(8, 0, 8, 0, 8, 8, 0, 0, 1), 0.1f));
|
||||
|
||||
for (int i = 0; i < 4; ++i)
|
||||
EXPECT_NO_THROW(updateWindow(w));
|
||||
|
||||
EXPECT_NO_THROW(viz3d::destroyObject(w, "pts"));
|
||||
destroyAllWindows();
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
Reference in New Issue
Block a user