VTK模块学习(一)
VTK模块学习(一)
VTK模块学习(一)
1、仅依赖于cmake编译好的VTK
推荐一篇博客:《VTK基础及应用开发教程》,版权归 @东灵工作室所有。
对于仅需cmake编译好的VTK实现可视化的人群,可参考此博客进行学习(干货多多)✨✨✨。
在此,演示如何创建一个简单的VTK程序 + 显示一个简单的VTK-3D实例。
流程如下:
①:新建一个文件夹名为Examples,然后在新建的文件夹下面再创一个文件夹名为TestVTKInstall。
②:在文件夹TestVTKInstall下创建一个bin文件夹、CMakeLists.txt以及TestVTKInstall.cpp文件。
③:在CMakeLists.txt文件里插入以下代码:
CMAKE_MINIMUM_REQUIRED(VERSION 3.13)
PROJECT(TestVTKInstall)
FIND_PACKAGE(VTK REQUIRED)
INCLUDE(${VTK_USE_FILE})
ADD_EXECUTABLE(TestVTKInstall TestVTKInstall.cpp)
TARGET_LINK_LIBRARIES(TestVTKInstall ${VTK_LIBRARIES})
在此详细说明一下这几行代码实现的功能,如下:
1、CMAKE_MINIMUM_REQUIRED 该命令用于指定构建工程时所需要的cmake版本要求。我自己的cmake版本时3.13.0,即VERSION后面所跟的版本号为3.13.0,第三个参数是可选的,0可不写。
2、PROJECT 该命令指定工程名称。可指定工程支持的语言,默认C\C++。存在两个隐含的cmake变量 <projectName>_BINARY_DIR 和 <projectName>_SOURCE_DIR,在这个例子里就是 TestVTKInstall_BINARY_DIR 以及 TestVTKInstall_SOURCE_DIR。同时cmake也预定义了 PROJECT_BINARY_DIR 和 PROJECT_SOURCE_DIR 变量,他们的值分别跟 <projectname>_BINARY_DIR 与 <projectname>_SOURCE_DIR一致。为了统一起见,以后直接使用 PROJECT_BINARY_DIR 和 PROJECT_SOURCE_DIR 分别表示工程的编译路径和源码路径,即这个例子里的 “F:\VTK\Examples\TestVTKInstall\bin” 和 “F:\VTK\Examples\TestVTKInstall”,因为这样即使修改了工程名称,也不会影响这两个变量。
3、FIND_PACKAGE 该命令用于搜索并加载外部工程。隐含的变量为 <package>_FOUND,用于标示是否搜索到所需的工程。参数 [REQUIRED] 表示所要搜索的外部工程对本工程来说是必须的,如果没有搜索到,cmake会终止整个工程构建过程。对VTK为例,FIND_PACKAGE命令搜索的就是VTK的配置文件 VTKConfig.cmake。
4、INCLUDE 指定载入一个文件或者模块,如果指定的是模块,那么将在CMAKE_MODULE_PATH中搜索这个模块并载入,在本例中,指定的是VTK模块,则会在CMAKE_MODULE_PATH中搜索VTK模块并载入,变量CMAKE_MODULE_PATH指的是搜索cmake模块的目录。本人的cmake模块目录为 “D:\cmake-3.13.0-rc1-win64-x64\share\cmake-3.13\Modules”,在该目录下,有FindVTK.cmake文件。在这个文件里我们发现就有变量VTK_USE_FILE的说明信息。
5、ADD_EXECUTABLE 定义这个工程会生成一个文件名为 <name> 的可执行文件。
6、TARGET_LINK_LIBRARIES 指定生成可执行文件时需要链接哪些文件。采用 ${VTK_LIBRARIES} 来获取需要的lib库名称。
④:在TestVTKInstall.cpp文件里插入以下代码:
#include "vtkRenderWindow.h"
#include "vtkSmartPointer.h"
int main()
{
//定义一个类型为vtkRenderWindow的对象
vtkRenderWindow *renWin = vtkRenderWindow::New();
//调用vtkRenderWindow里的方法显示并渲染VTK窗口
renWin->Render();
//使程序暂停下来,等待用户的输入
std::cin.get();
return 0;
}
⑤:打开cmake程序,在cmake的“Where is the source code”一栏输入路径:F:/VTK/Examples/TestVTKInstall,在“Where to build the binaries”一栏输入路径:F:/VTK/Examples/TestVTKInstall/bin,接着按“Configure”按钮。

⑥:点击Finish后,会出现如下错误提示窗口(原因:由于在编译生成的VTK的时候,修改了VTK_Install的默认路径)。

⑦:点击OK后,修改VTK_DIR。

⑧:点击Configure。

⑨:点击Generate。

⑩:在TestVTKInstall点击右键,设置为启动项目。

⑪:点击运行,系统错误(找不到有关vtk相关的dll文件)。

⑫:解决方法:右键项目->属性->调试,将环境设置为如下路径,并保存。
PATH=F:\VTK\VTK_Install\bin;%PATH%

⑬:点击运行(发现并没有VTK效果图展示出来),如图所示:

⑭:解决方法:添加如下代码,运行,如图所示:
#include "vtkAutoInit.h"
//VTK是用vtkRenderingOpenGL2构建的(用于显示VTK窗体)
VTK_MODULE_INIT(vtkRenderingOpenGL2);
//Warning: Link to vtkInteractionStyle for default style selection(警示)
VTK_MODULE_INIT(vtkInteractionStyle);

⑮:举例上述推荐博客中 03-VTK基础概念(1) 的代码,运行,如图所示:

/********************************************************************/
/*
运行的效果图可以使用鼠标与其进行交互
1、 用鼠标滚轮可以对柱体放大、缩小
2、 按下鼠标左键不放,然后移动鼠标,可以转动柱体
3、 按下鼠标左键,同时按下Shift键,移动鼠标,可以移动整个柱体
4、 按下Ctrl键时再按鼠标左键 只可旋转柱体
……………………
*/
/********************************************************************/
#include "vtkSmartPointer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderer.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkInteractorStyleTrackballCamera.h"
#include "vtkCylinderSource.h"
#include "vtkPolyDataMapper.h"
#include "vtkActor.h"
#include "vtkBMPReader.h"
#include "vtkTexture.h"
#include "vtkAutoInit.h"
//VTK是用vtkRenderingOpenGL2构建的(用于显示VTK窗体)
VTK_MODULE_INIT(vtkRenderingOpenGL2);
//Warning: Link to vtkInteractionStyle for default style selection(警示)
VTK_MODULE_INIT(vtkInteractionStyle);
int main()
{
//读取图片数据
vtkSmartPointer<vtkBMPReader> bmpReader = vtkSmartPointer<vtkBMPReader>::New();
bmpReader->SetFileName("ganxie.bmp");
//将读入的图片传入texture
vtkSmartPointer<vtkTexture> texture = vtkSmartPointer<vtkTexture>::New();
texture->SetInputConnection(bmpReader->GetOutputPort());
texture->InterpolateOn();
//vtkCylinderSource派生自vtkPolyDataAlgorithm
//生成一个中心在渲染场景原点的柱体,柱体的长轴沿着Y轴,柱体的高度、截面半径等都可以任意指
vtkSmartPointer<vtkCylinderSource> cylinder = vtkSmartPointer<vtkCylinderSource>::New();
//设置柱体的高
cylinder->SetHeight(3.0);
//设置柱体截面的半径
cylinder->SetRadius(1.0);
//设置柱体横截面的等边多边形的边数
cylinder->SetResolution(10);
//vtkPolyDataMapper派生自类vtkMapper,将输入的数据转换为几何图元(点、线、多边形)进行渲染。
vtkSmartPointer<vtkPolyDataMapper> cylinderMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
//VTK可视化管线的输入数据接口(功能暂时未知)
cylinderMapper->SetInputConnection(cylinder->GetOutputPort());
//vtkActor派生自vtkProp类,作用:渲染场景中数据的可视化表达(具体参考提供博客详解)
vtkSmartPointer<vtkActor> cylinderActor = vtkSmartPointer<vtkActor>::New();
//设置生成几何图元的Mapper。即连接一个Actor到可视化管线的末端(可视化管线的末端就是Mapper)。
cylinderActor->SetMapper(cylinderMapper);
cylinderActor->SetTexture(texture);
//vtkRenderer派生自vtkViewport类,作用:负责管理场景的渲染过程。一个vtkRenderWindow中可以有多个vtkRenderer对象,而这些vtkRenderer可以渲染在窗口中不同的矩形区域中(即视口),或者覆盖整个窗口区域。
vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
//添加vtkProp类型的对象到渲染场景中
renderer->AddActor(cylinderActor);
//用于设置渲染场景的背景颜色,用R、G、B的格式设置,三个分量的取值为0.0~ 1.0。(0.0,0.0, 0.0)为黑色,(1.0,1.0, 1.0)为白色。
renderer->SetBackground(0.1, 0.2, 0.4);
//vtkRenderWindow派生自vtkViewport类,作用:将操作系统与VTK渲染引擎连接到一起。
vtkSmartPointer<vtkRenderWindow> renWin = vtkSmartPointer<vtkRenderWindow>::New();
//加入vtkRenderer对象
renWin->AddRenderer(renderer);
//用于设置窗口的大小,以像素为单位
renWin->SetSize(300, 300);
//vtkRenderWindowInteractor派生自vtkObject类,作用:提供平台独立的响应鼠标、键盘和时钟事件的交互机制。
vtkSmartPointer<vtkRenderWindowInteractor> iren = vtkSmartPointer<vtkRenderWindowInteractor>::New();
//设置渲染窗口,消息是通过渲染窗口捕获到的,所以必须要给交互器对象设置渲染窗口。
iren->SetRenderWindow(renWin);
//vtkInteractorStyleTrackballCamera派生自vtkInteractorStyle类,交互器样式的一种,该样式下,用户是通过控制相机对物体作旋转、放大、缩小等操作。
vtkSmartPointer<vtkInteractorStyleTrackballCamera> style = vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New();
//设置交互器样式
iren->SetInteractorStyle(style);
//初始化交互窗口
iren->Initialize();
//启动窗口事件循环
iren->Start();
return 0;
}

2、基于OpenCV编译下的VTK
由于没有找到具体的参考文献(渴求:如果谁有整系列的(前提是免费的)可以告诉我,我会整理出来给大家分享哦,感谢💌💌💌),在此只能根据一些实例进行学习。
实例一:
void Example_1()
{
//创建可视化窗口
//参数1 窗口名称
//Viz3d(const String& window_name = String());
cv::viz::Viz3d window("Example_1");
//构造一个坐标系部件,并显示到可视化窗口中
//参数1 定义部件ID,用于后面定位到此部件
//参数2 viz::WCoordinateSystem() -> 坐标系部件
//参数3 默认值Affine3d::Identity()
//void showWidget(const String &id, const Widget &widget, const Affine3d &pose = Affine3d::Identity());
//红颜色的坐标轴为x轴,绿颜色的坐标轴为y轴, 蓝颜色的坐标轴为z轴
window.showWidget("Coordinate", cv::viz::WCoordinateSystem());
//WPlane为平面类,继承与Widget3D类--存在两个构造函数
//构造一个默认平面,中心点在原点,法向沿z轴方向
//参数1 平面大小
//参数2 平面颜色
//WPlane(const Size2d& size = Size2d(1.0, 1.0), const Color &color = Color::white());
//构造一个重新定位的平面
//参数1 平面中心点
//参数2 平面法向量方向
//参数3 平面y轴的新方向
//参数4 平面大小
//参数5 平面颜色
//WPlane(const Point3d& center, const Vec3d& normal, const Vec3d& new_yaxis, const Size2d& size = Size2d(1.0, 1.0), const Color &color = Color::white());
cv::viz::WPlane plane1(cv::Size2d(1.0, 1.0), cv::viz::Color::red());
//添加平面部件,并显示到可视化窗口中
window.showWidget("plane1", plane1);
//创建平面
cv::viz::WPlane plane2(cv::Point3d(0.5,0.0,0.5), cv::Vec3d(1.0, 0.0, 0.0), cv::Vec3d(0.0, 1.0, 0.0), cv::Size(1.0, 1.0), cv::viz::Color::white());
//添加平面部件,并显示到可视化窗口中
window.showWidget("plane2", plane2);
//创建平面
cv::viz::WPlane plane3(cv::Point3d(0.0, 0.0, 1), cv::Vec3d(0.0, 0.0, 1.0), cv::Vec3d(0.0, 1.0, 0.0), cv::Size(1.0, 1.0), cv::viz::Color::red());
//添加平面部件,并显示到可视化窗口中
window.showWidget("plane3", plane3);
//创建平面
cv::viz::WPlane plane4(cv::Point3d(-0.5, 0.0, 0.5), cv::Vec3d(1.0, 0.0, 0.0), cv::Vec3d(0.0, 1.0, 0.0), cv::Size(1.0, 1.0), cv::viz::Color::white());
//添加平面部件,并显示到可视化窗口中
window.showWidget("plane4", plane4);
//永久循环暂留
//spin()函数开启一个事件永远循环。直观的用处就是让画面停在那里
//按q键或者e键,可结束循环
//void spinOnce(int time = 1, bool force_redraw = false);此函数是该函数的变种,可指定循环事件time(以毫秒为单位),参数force_redraw(暴力重画),作用未知
window.spin();
}
效果展示

实例二:
void Example_2()
{
//创建一个可视化窗体
cv::viz::Viz3d window("Example_2");
//构造一个坐标系部件,并显示到可视化窗口中
window.showWidget("Coordinate", cv::viz::WCoordinateSystem());
//创建平面部件
cv::viz::WPlane plane;
//添加平面部件,并显示到可视化窗口中
window.showWidget("plane", plane);
//创建一个1 * 3的Mat矩阵(罗德里格斯向量)
cv::Mat rvec = cv::Mat::zeros(1, 3, CV_32F);
//动画的本质:调整部件位姿并循环显示,控制条件是窗口没被停止。
//但主动按下了q或者e键,停止显示动画
while (!window.wasStopped())
{
rvec.at<float>(0, 0) = 0.f;
rvec.at<float>(0, 1) += CV_PI * 0.01f;
rvec.at<float>(0, 2) = 0.f;
//罗德里格斯向量->旋转矩阵
cv::Mat rmat;
//罗德里格斯公式,将罗德里格斯向量转换成旋转矩阵
cv::Rodrigues(rvec, rmat);
//构造仿射变换类型的pose,这个类型暂且看做OpenCV中的位姿类型,两个参数,一个旋转,一个平移
cv::Affine3f pose(rmat, cv::Vec3f(0, 0, 0));
//这一句就是整个可视化窗口能够动起来的核心语句了,
//说白了就是利用循环来不断调整上面plane部件的位姿,达到动画的效果
//设置部件在可视化窗口中的姿态
//参数1 需要设置姿态的部件ID
//参数2 部件的新姿态
//void setWidgetPose(const String &id, const Affine3d &pose);
window.setWidgetPose("plane", pose);
//设置单帧暂留时间,time是以毫秒为单位
window.spinOnce(1, false);
}
}
效果展示

实例三:
void Example_3()
{
//创建可视化窗口
cv::viz::Viz3d window("Example_3");
//构造一个坐标系部件,并显示到可视化窗口中
window.showWidget("Coordinate", cv::viz::WCoordinateSystem());
//设置可视化窗口背景颜色
//参数1 输入颜色(只输入参数1,只显示参数1指定的颜色)
//参数2 输入颜色(若同时输入参数1、参数2,则二值同时显示)
//Color::not_set() = Color(-1, -1, -1) 黑色
//void setBackgroundColor(const Color& color = Color::black(), const Color& color2 = Color::not_set());
window.setBackgroundColor(cv::viz::Color(200, 50, 100), cv::viz::Color(50, 200, 100));
//创建平面
cv::viz::WPlane plane(cv::Size2d(2.0, 2.0), cv::viz::Color(13, 255, 39));
//设置平面属性
//参数1 修改属性 POINT_SIZE(点大小) OPACITY(透明度) LINE_WIDTH(线宽) FONT_SIZE(字体大小)
//参数2 新的属性值
//void setRenderingProperty(int property, double value);
plane.setRenderingProperty(cv::viz::OPACITY, 0.5);
//设置平面姿态
//参数1 cv::Affine3f() 4 x 4 的单位矩阵
plane.setPose(cv::Affine3f());
//添加平面部件,并显示到可视化窗口中
window.showWidget("plane", plane);
//创建线条
//参数1 线条的起始点
//参数2 线条的终点
//线条的颜色
//WLine(const Point3d &pt1, const Point3d &pt2, const Color &color = Color::white());
cv::viz::WLine line(cv::Point3d(0.0, 0.0, 0.0), cv::Point3d(10.0, 10.0, 0.0), cv::viz::Color::yellow());
//设置线条属性
line.setRenderingProperty(cv::viz::LINE_WIDTH, 2);
//设置线条姿态
line.setPose(cv::Affine3f());
//添加线条部件,并显示到可视化窗口中
window.showWidget("line", line);
//创建球体
//参数1 球体的中心
//参数2 球体的半径
//参数3 球体分辨率
//参数4 球体颜色
//WSphere(const cv::Point3d ¢er, double radius, int sphere_resolution = 10, const Color &color = Color::white());
cv::viz::WSphere sphere(cv::Point3d(-10, -10, -10), 3, 100, cv::viz::Color::blue());
//设置球体属性
sphere.setRenderingProperty(cv::viz::LINE_WIDTH, 2);
//添加球体部件,并显示在可视化窗口中
window.showWidget("sphere", sphere);
//创建箭头
//参数1 箭头开始点
//参数2 箭头结束点
//参数3 箭头头的厚度
//参数4 箭头的颜色
//箭头的头部位于结束点
//WArrow(const Point3d& pt1, const Point3d& pt2, double thickness = 0.03, const Color &color = Color::white());
cv::viz::WArrow warrow(cv::Point3d(-10, -10, -10), cv::Point3d(0, 0, 0), 0.03, cv::viz::Color::red());
//设置箭头属性
warrow.setRenderingProperty(cv::viz::LINE_WIDTH, 2);
//添加箭头部件,并显示到可视化窗口中
window.showWidget("warrow", warrow);
//创建平面圆,圆心在原点,平面法线沿z轴
//参数1 平面圆的半径
//参数2 平面圆的厚度(线宽)
//参数3 平面圆的颜色
//WCircle(double radius, double thickness = 0.01, const Color &color = Color::white());
cv::viz::WCircle wcricle(3.0, 0.01, cv::viz::Color::navy());
//设置平面圆属性
wcricle.setRenderingProperty(cv::viz::LINE_WIDTH, 1);
//添加平面圆部件,并显示在可视化窗口中
window.showWidget("wcricle", wcricle);
//有序点列
std::vector<cv::Point3d> points3d;
for (int i = 0; i < 5; i++)
{
points3d.push_back(cv::Point3d(i, i * 2, 0));
}
//创建多线段
//参数1 有序点列
//参数2 多线段颜色
//WPolyLine(InputArray points, const Color &color = Color::white());
//WPolyLine(InputArray points, InputArray colors);
cv::viz::WPolyLine wpolyLine(points3d, cv::viz::Color::rose());
//设置多线段属性
wpolyLine.setRenderingProperty(cv::viz::LINE_WIDTH, 2);
//添加多线段部件,并显示在可视化窗口中
window.showWidget("wpolyLine", wpolyLine);
std::vector<cv::Point3d> pointCloud;
pointCloud.resize(points3d.size());
for (size_t i = 0; i < points3d.size(); i++)
{
pointCloud[i] = points3d[i] * 3;
}
//创建点云
//在云边界点之间使用默认梯度绘制云
//WPaintedCloud(InputArray cloud);
//在给定的点之间使用默认渐变绘制云
//WPaintedCloud(InputArray cloud, const Point3d& p1, const Point3d& p2);
//用给定的颜色在给定的点之间绘制渐变云
//WPaintedCloud(InputArray cloud, const Point3d& p1, const Point3d& p2, const Color& c1, const Color c2);
cv::viz::WPaintedCloud wpaintedCloud(pointCloud);
//设置点云属性
wpaintedCloud.setRenderingProperty(cv::viz::POINT_SIZE, 6);
//添加点云部件,并显示在可视化窗口中
window.showWidget("wpaintedCloud", wpaintedCloud);
//创建网格
//参数1 单元格的列数和行数
//参数2 每个单元格的大小
//参数2 网格颜色
//WGrid(const Vec2i &cells = Vec2i::all(10), const Vec2d &cells_spacing = Vec2d::all(1.0), const Color &color = Color::white());
//创建自定义网格
//参数1 网格中心坐标
//参数2 网格法向量方向
//参数3 网格y轴的新方向
//参数4 单元格的列数和行数
//参数5 每个单元格的大小
//参数6 网格颜色
//WGrid(const Point3d& center, const Vec3d& normal, const Vec3d& new_yaxis, const Vec2i &cells = Vec2i::all(10), const Vec2d &cells_spacing = Vec2d::all(1.0), const Color &color = Color::white());
cv::viz::WGrid wgrid(cv::Vec2i::all(10), cv::Vec2d::all(1.0), cv::viz::Color::white());
//添加网格部件,并显示在可视化窗口中
window.showWidget("wgrid", wgrid);
//创建立方体
//参数1 指定包围框的最小(或最大)点
//参数2 指定包围框的最大(或最小)点
//参数3 wire_frame如果为true,立方体表示为线框
//参数4 立方体颜色
//WCube(const Point3d& min_point = Vec3d::all(-0.5), const Point3d& max_point = Vec3d::all(0.5), bool wire_frame = true, const Color &color = Color::white());
cv::viz::WCube wcube(cv::Vec3d::all(-5), cv::Vec3d::all(5), true, cv::viz::Color::cherry());
//设置立方体属性
wcube.setRenderingProperty(cv::viz::LINE_WIDTH, 2);
//添加立方体部件,并显示在可视化窗口中
window.showWidget("wcube", wcube);
//创建文本(2D)
//参数1 文本内容
//参数2 文本位置
//参数3 文本字体大小
//参数4 文本颜色
//WText(const String &text, const Point &pos, int font_size = 20, const Color &color = Color::white());
cv::viz::WText wtext("OpenCV", cv::Point2i(100, 100), 20, cv::viz::Color::green());
//添加文本(2D)部件,并显示在可视化窗口中
window.showWidget("wtext", wtext);
//创建文本(3D)
//参数1 文本内容
//参数2 文本位置信息
//参数3 文本字体大小
//参数4 face_camera = true 文本总是面对镜头
//参数5 文本颜色
//WText3D(const String &text, const Point3d &position, double text_scale = 1., bool face_camera = true, const Color &color = Color::white());
cv::viz::WText3D wtext3d("OpenCV", cv::Point3d(10, 10, 10), 3.1, false, cv::viz::Color::white());
//添加文本(3D)部件,并显示在可视化窗口中
window.showWidget("wtext3d", wtext3d);
std::vector<cv::Affine3f> pointPose;
//创建一个1 * 3的Mat矩阵(罗德里格斯向量)
cv::Mat rvec = cv::Mat::zeros(1, 3, CV_32F);
for (size_t i = 0; i < 0; i++)
{
rvec.at<float>(0, 0) = 0.f;
rvec.at<float>(0, 1) += CV_PI * 0.01f;
rvec.at<float>(0, 2) = 0.f;
//罗德里格斯向量->旋转矩阵
cv::Mat rmat;
//罗德里格斯公式,将罗德里格斯向量转换成旋转矩阵
cv::Rodrigues(rvec, rmat);
//构造仿射变换类型的pose,这个类型暂且看做OpenCV中的位姿类型,两个参数,一个旋转,一个平移
cv::Affine3f pose(rmat, cv::Vec3f(0, 0, 0));
pointPose.push_back(pose);
}
//创建轨迹(此实例报错)
//参数1 path轨迹上的姿态列表。采用std::vector<Affine<T>> 且 T == [float | double]
//参数2 显示模式。可以是PATH, FRAMES,或者两者都是。
//参数3 框架的比例。Polyline不受影响。
//参数4 表示路径折线的颜色
//单帧不受影响
// PATH:显示一条代表路径的多边形线
// FRAMES:显示每个姿势的坐标帧
// PATH & FRAMES:同时显示多边形和坐标帧
//WTrajectory(InputArray path, int display_mode = WTrajectory::PATH, double scale = 1.0, const Color &color = Color::white());
//cv::viz::WTrajectory wtrajectory(pointPose, cv::viz::WTrajectory::PATH & cv::viz::WTrajectory::FRAMES, 1.0, cv::viz::Color::green());
//设置轨迹属性
//wtrajectory.setRenderingProperty(cv::viz::LINE_WIDTH, 5);
//添加轨迹部件,并现在在可视化窗口中
//window.showWidget("wtrajectory", wtrajectory);
//重新赋值(罗德里格斯向量)
rvec = cv::Mat::zeros(1, 3, CV_32F);
//动画的本质:调整部件位姿并循环显示,控制条件是窗口没被停止。
//但主动按下了q或者e键,停止显示动画
while (!window.wasStopped())
{
rvec.at<float>(0, 0) = 0.f;
rvec.at<float>(0, 1) += CV_PI * 0.01f;
rvec.at<float>(0, 2) = 0.f;
//罗德里格斯向量->旋转矩阵
cv::Mat rmat;
//罗德里格斯公式,将罗德里格斯向量转换成旋转矩阵
cv::Rodrigues(rvec, rmat);
//构造仿射变换类型的pose,这个类型暂且看做OpenCV中的位姿类型,两个参数,一个旋转,一个平移
cv::Affine3f pose(rmat, cv::Vec3f(0, 0, 0));
//设置部件在可视化窗口中的姿态
window.setWidgetPose("plane", pose);
//设置单帧暂留时间,time是以毫秒为单位
window.spinOnce(1, true);
}
window.removeAllWidgets();
}
效果展示

实例四:
void Example_4()
{
//创建一个可视化窗体
cv::viz::Viz3d window("Example_4");
//构造一个坐标系部件,并显示到可视化窗口中
window.showWidget("Coordinate Widget", cv::viz::WCoordinateSystem());
//创建线条
cv::viz::WLine line(cv::Point3f(-1.0f, -1.0f, -1.0f), cv::Point3f(1.0f, 1.0f, 1.0f));
//设置线条属性
line.setRenderingProperty(cv::viz::LINE_WIDTH, 4.0);
//添加线条部件,并显示到可视化窗口中
window.showWidget("Line Widget", line);
//创建立方体
cv::viz::WCube cube(cv::Point3f(0.5, 0.5, 0.0), cv::Point3f(0.0, 0.0, -0.5), true, cv::viz::Color::blue());
//设置立方体属性
cube.setRenderingProperty(cv::viz::LINE_WIDTH, 4.0);
//添加立方体部件,并显示到可视化窗口中
window.showWidget("Cube Widget", cube);
//创建一个1 * 3的Mat矩阵(罗德里格斯向量)
cv::Mat rot_vec = cv::Mat::zeros(1, 3, CV_32F);
float translation_phase = 0.0, translation = 0.0;
//判断事件循环是否暂停
while (!window.wasStopped())
{
//使用旋转罗德里格斯
//旋转范围(1,1,1)
rot_vec.at<float>(0, 0) += CV_PI * 0.01f;
rot_vec.at<float>(0, 1) += CV_PI * 0.01f;
rot_vec.at<float>(0, 2) += CV_PI * 0.01f;
//转变(1,1,1)
translation_phase += CV_PI * 0.01f;
translation = sin(translation_phase);
//罗德里格斯公式,将罗德里格斯向量转换成旋转矩阵
cv::Mat rot_mat;
Rodrigues(rot_vec, rot_mat);
//构造仿射变换类型的pose
cv::Affine3f pose(rot_mat, cv::Vec3f(translation, translation, translation));
//设置部件在可视化窗口中的姿态
window.setWidgetPose("Cube Widget", pose);
//设置单帧暂留时间,time是以毫秒为单位
window.spinOnce(1, true);
}
}
效果展示

实例五:
void Example_5()
{
//创建一个可视化窗口
cv::viz::Viz3d window("Example_5");
//构造一个坐标系部件,并显示到可视化窗口中
window.showWidget("Coordinate Widget", cv::viz::WCoordinateSystem());
//创建线段
cv::viz::WLine line(cv::Point3f(0.f, 0.f, 0.f), cv::Point3f(2.f, 2.f, 2.f), cv::viz::Color::yellow());
//设置线段属性
line.setRenderingProperty(cv::viz::LINE_WIDTH, 1.0);
//添加线段部件,并显示在可视化窗口中
window.showWidget("Line Widget", line);
//初始化(相机位置、焦点、向上向量)
cv::Vec3f cam_pos(2.0f, 2.0f, 2.0f);
cv::Vec3f cam_focal_point(3.0f, 3.0f, 3.0f);
cv::Vec3f cam_y_dir(-0.f, 0.0f, -1.0f);
//从位置、焦点和向上向量构造相机姿态
//参数1 相机在全局坐标系中的位置
//参数2 相机在全局坐标系中的焦点
//参数3 相机在全局坐标系中的上向量
//这个函数返回相机在全局坐标系中的姿态
//Affine3d makeCameraPose(const Vec3d& position, const Vec3d& focal_point, const Vec3d& y_dir);
cv::Affine3f cam_pose = cv::viz::makeCameraPose(cam_pos, cam_focal_point, cam_y_dir);
//在原点创建相机坐标框架
//(相机坐标系)(images/cpw1.png)
//WCameraPosition(double scale = 1.0);
cv::viz::WCameraPosition cp(1);
//显示视锥
//参数1 相机的视场(水平和垂直)
//参数2 截锥的比例
//参数3 截锥的颜色
//基于相机的固有矩阵K创建相机的视锥
//(相机观察平截头体)(images/cpw2.png)
//WCameraPosition(const Vec2d &fov, double scale = 1.0, const Color &color = Color::white());
cv::viz::WCameraPosition cp_frustum(cv::Vec2f(0.889484, 0.523599));
//添加相机坐标部件,并显示在可视化窗口中
window.showWidget("CPW", cp, cam_pose);
//添加视锥部件,并显示在可视化窗口中
window.showWidget("CPW_FRUSTUM", cp_frustum, cam_pose);
//永久循环暂留
window.spin();
}
效果展示

实例六:
void Example_6()
{
//创建一个可视化窗口
cv::viz::Viz3d window("Example_6");
//构建一个坐标系部件,并显示在可视化窗口中
window.showWidget("Coordinate Widget", cv::viz::WCoordinateSystem());
//初始化(相机位置、焦点、向上向量)
cv::Vec3f cam_pos(3.0f, 3.0f, 3.0f);
cv::Vec3f cam_focal_point(3.0f, 3.0f, 2.0f);
cv::Vec3f cam_y_dir(-1.0f, 0.0f, 0.0f);
//从位置、焦点和向上向量构造相机姿态
cv::Affine3f cam_pose = cv::viz::makeCameraPose(cam_pos, cam_focal_point, cam_y_dir);
//取坐标系数据,建立到全局坐标系的变换
//参数1 全局坐标系中的X轴向量
//参数2 全局坐标系中的Y轴向量
//参数3 全局坐标系中的Z轴向量
//参数4 坐标系在全局坐标系中的原点
//一个仿射变换,描述全局坐标系和给定坐标系之间的变换。返回的转换可以将给定坐标系中的一个点转换为全局坐标系
//Affine3d makeTransformToGlobal(const Vec3d& axis_x, const Vec3d& axis_y, const Vec3d& axis_z, const Vec3d& origin = Vec3d::all(0));
cv::Affine3f transform = cv::viz::makeTransformToGlobal(cv::Vec3f(0.0f, -1.0f, 0.0f), cv::Vec3f(-1.0f, 0.0f, 0.0f), cv::Vec3f(0.0f, 0.0f, -1.0f), cam_pos);
cv::Mat bunny_cloud(1, 1889, CV_32FC3);
std::ifstream ifs("bunny.ply");
std::string str;
for (size_t i = 0; i < 13; i++)
getline(ifs, str);
cv::Point3f *data = bunny_cloud.ptr<cv::Point3f>();
float dummy1, dummy2;
for (size_t i = 0; i < 1889; i++)
ifs >> data[i].x >> data[i].y >> data[i].z >> dummy1 >> dummy2;
bunny_cloud *= 5.0f;
//创建点云
cv::viz::WCloud cloud(bunny_cloud, cv::viz::Color::green());
cv::Affine3f cloud_pose = cv::Affine3f().translate(cv::Vec3f(0.0f, 0.0f, 3.0f));
cv::Affine3f cloud_pose_global = transform * cloud_pose;
//添加点云部件,并显示在可视化窗口中
window.showWidget("bunny", cloud, cloud_pose_global);
//永久循环暂留
window.spin();
//设置观察者新姿态
//void setViewerPose(const Affine3d &pose);
window.setViewerPose(cam_pose);
//永久循环暂留
window.spin();
}
效果展示

整体代码框架如下:
#include <opencv2/viz.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/calib3d.hpp>
#include <iostream>
#include <fstream>
//导入opencv库
#ifdef _DEBUG
#pragma comment(lib,"../CV453/opencv_img_hash453d.lib")
#pragma comment(lib,"../CV453/opencv_world453d.lib")
#else
#pragma comment(lib,"../CV453/opencv_world453.lib")
#pragma comment(lib,"../CV453/opencv_img_hash453d.lib")
#endif
void Example_1()
{
}
void Example_2()
{
}
void Example_3()
{
}
void Example_4()
{
}
void Example_5()
{
}
void Example_6()
{
}
int main()
{
//按q键或e键跳转到下一个函数接口
Example_1();
Example_2();
Example_3();
Example_4();
Example_5();
Example_6();
return 0;
}
以上代码来源:
博客1:robinhjwy
博客2:JackRuiYu
博客3:jsxyhelu
博客4:知识在于分享
兔子点云文件(来源于:时光不遇拾光):
链接:https://pan.baidu.com/s/1IJeQvJC4KWWnuspMqYjTRw
提取码:zmdf
更多推荐

所有评论(0)