VTK模块学习(一)

VTK基础教程(1)- vtkPolyData 介绍 目录 VTK的编译与环境搭建 VTK一般渲染流程 VTK数据类型-vtkPolyData 使用vtk自带的多边形数据 使用自己创建的数据 添加顶点颜色 添加面颜色 VTK的编译与环境搭建 这部分目前已经有了大佬做了成熟的傻瓜式配置,大家可以参考这篇文章:VTK+VS2019(或其他版本均可) 傻瓜式一站式 配置_Nancy_fairy的博客-CSDN博客_vs2019 vtk VTK一般渲染流程 这部分的介绍也很多,大家可以参考这篇文章: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 &center, 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

VTK使用指南:介绍 本章讨论了开发大型和/或复杂软件系统的一些问题,并描述了面向对象设计如何解决其中的许多问题。本章定义了面向对象建模和设计中使用的关键术语,并通过一个真实世界的例子进行了工作。本章最后简要介绍了一些面向对象的语言以及与面向对象可视化相关的一些问题。 阅读详情

相关推荐

VTK修炼之道1_初识VTK

1.VTK是什么? Visualization ToolKit 3D计算机图形学、图象处理及可视化工具包 VTK使用C++、面向对象技术开发;基于OpenGL,封装了OpenGL中的功能,屏蔽细节、便于交互、易于使用提供多种语言接口C++ 、Java 、Tcl、 Python 等;可在Windows 98/NT, SGI, Linux,  Sun, HP等系统编译

沈春旭的博客 1万+

VTK 基本介绍

VTK(Visualization Toolkit)是 Kitware 公司发布的开源免费软件系统,受到国内外高等院校与科研机构的欢迎,广泛地应用于计算机图形学、图像处理与三维可视化等领域。VTK 独立于系统的图形界面接口(GUI),可方便的嵌入到其他的相关软件中。同时开发人员可以基于 VTK 独立的基础类库开发自己的库函数,拓展 VTK 的应用范围。 VTK 采用面向对象思想,基于 OpenGL 开发出目标函数库。它将将一些常用的算法封装为类的形式,用户在开发过程中可以直接调...

钢铁男儿 2万+

基于C++的VTK8学习笔记4(VTK体绘制)

第七章 VTK体绘制 实例59:体绘制管线(光线投影法体绘制) #include <vtkAutoInit.h> VTK_MODULE_INIT(vtkRenderingOpenGL2); VTK_MODULE_INIT(vtkRenderingVolumeOpenGL2); //错误:no override found for 'vtkRayCastImageDisplayHelper'. VTK_MODULE_INIT(vtkRenderingFreeType); VT

qq_32809093的博客 4640

VTK修行之相见恨晚

开启我的VTK之路

保持分享欲 2343

VTK系列教程一:整体架构

VTK(Visualization Toolkit ),顾名思义主要用于三维计算机图形学、图像处理和可视化,VTK到底能做什么?这还得从人类的视觉系统讲起,现实世界中的物体在光照的作用下,其反射的光线进入人体视神经网络形成图像,物体、光照、视神经网络在VTK中都有对应的抽象,VTK正是利用这种抽象来模拟人类的视觉系统,将图像绘制到计算机屏幕上;那么大家都听过数字图像处理这门课,它与VTK不同,它是利用各种变换和算法来提取图像中的特征,例如,滤波、傅里叶变换、分割等;而VTK的主要功能是绘制,本系列教程就以一

计算机视觉大讲堂 8813

基于C++的水灵VTK8学习笔记1(VTK基本概念)

张晓东的《VTK图形图像开发进阶》全套资料(包含书籍电子版,配套每章节所有源码、实现效果图和工程配置文件): https://download.csdn.net/download/qq_32809093/12550945 水灵VTK学习全套资料(包含全部视频、PPT、源码和每个项目对应的工程配置文件CmakeLists.txt): https://download.csdn.net/download/qq_32809093/12550933 水灵VT视频在线观看:https://www.ixigua.c

qq_32809093的博客 2012

01-从零开始学习VTK

1、从零开始学习VTK 可能在这之前你没有使用过VTK,甚至不知道VTK是什么东西。这里假定你没有一点VTK基础,但已经有了一些基本的C/C++编程基础,以及计算机图形学的理论知识储备,想使用VTK从事相关的项目开发,又不想查看VTK海量的英文文档,但又想快速入门。 好吧,废话少说。从VTK最基础的部分开始学起。 1.1        什么是VTK? VTK,全称为Visualizatio

东灵工作室 7万+

VTK 学习初步

VTK相关的基础知识VTK,visualization toolkit,可视化工具包,主要应用于三维计算机图形、图像处理和可视化方面。它在三维函数库OpenGL的基础上采用面向对象的设计方法发展而来,且具有跨平台的特性。 VTK面向对象,含有大量的对象模型。 源对象是可视化流水线的起点,映射器(Mapper)对象是可视化流水线的终点,是图形模型和可视化模型之间的接口. 回调(或用户方法):

theArcticOcean 5453

VTK 学习笔记

VTK 是什么 VTK,Visualization Tool Kit,可视化工具包。 VTK 是一个用于图像处理、三维图形、体绘制(通过模拟光线穿越半透明物体时的能量变化来绘制物体,即采用体光照模型对三维体数据场进行直接显示)、可视化的开源软件系统。 VTK 架构 VTK 库的框架结构 vtkObject -> vtkSource -> vtkFilter -> vtkMapper -> vtkActor -> vtkRenderer vtkObject vtkObject 是

TEDxPY 3388

【VTK】在Mac上学习VTK

MAC OS X上的编译: https://www.vtk.org/Wiki/VTK/Building/MacOSX 编译vtk使得QT版本为5 cmake configure: cmake ./ -G &amp;quot;Unix Makefiles&amp;quot; \ -DVTK_USE_QVTK:BOOL=ON \ -DCMAKE_INSTALL_PREFIX=/usr/local \ -DVTK_US...

theArcticOcean 2469

VTK学习(一)

VTK采用管道过滤器结构,有两点要注意: 1.过滤器不改变源数据 2.如要保存过滤器的输出数据,不能简单的指针赋值,要研究其存放数据的数据结构,将数据拷贝到新创建的内存空间中。 VTK的基本框架 一、图形模型:source+filter 数据流对象:vtkDataObject+vtkProcessObject 关键类关系继承图如下: 关于vtkDataObject

u013089125的专栏 1569

VTK学习之一(基本介绍、一个简单的VTK例子)

这篇主要讲一个VTK的简单例子,加深自己对VTK的理解。 前记 学习vtk就是觉得pcl中封装的PCLVisualizer功能有限。学习vtk主要是看《VTK图形图像开发进阶》张晓东、罗火灵编著这本书,还有就是水灵的视频。水灵的视频更加老一点,不是很影响对vtk的基本理解,我是看了一遍书之后再看水灵的视频,还是看视频理解来的更加深刻。 水灵用的版本是vtk5.6版本,东灵用的是vtk6.0版本,我用的版本是vtk8.0。 VTK介绍 VTK全称Visualization...

qq_42570058的博客 1万+

VTK学习(三)VTK读取序列图像

VTKstd在VTK7版本中不再使用,用std替代 VTK7中需添加命名空间 using namespace std; std::string fileStr(fileName); #include "vtkAutoInit.h" VTK_MODULE_INIT(vtkRenderingOpenGL2); // VTK was built with vtkRenderingOpenGL

yuyangyg的博客 2007

VTK学习笔记(九)VTK中的各个模块

VTK中的各个模块1、各个模块2、各个模块的作用 1、各个模块 在前面的几个示例中CMakeLists.txt中有涉及到VTK的组件,因此要整理以下各个组件的作用,以及包含的内容。 如下: find_package(VTK COMPONENTS vtkCommonCore vtkCommonDataModel vtkImagingCore vtkInteractionStyle vtkRenderingContextOpenGL2 vtkRenderingCore vtkRen

juluwangriyue的博客 2634

头歌MySQL数据库实训答案 有目录

头歌java实训答案集数据库部分一条一条的写,可鼠标手动粘贴,除特定命令外未分大小写。 第1关:创建数据库 第2关创建表 第3关:使用主键约束 第4关:外键约束 第5关:添加常用约束 MySQL数据库 - 数据库和表的基本操作(一) 第1关:查看表结构与修改表名 第2关:修改字段名与字段数据类型 第3关:添加与删除字段 第4关:修改字段的排列位置 第5关:删除表的外键约束 MySQL数据库 - 数据库和表的基本操作(二) 第1关:插入数据 第2关:更新数据 第3关:删除数据 MySQL数据库 - 单表查询(

m0_67401761的博客 4万+

手把手教你用Microsoft AEC Challenge数据集训练自己的回声消除模型(附完整代码)

本文详细介绍了如何使用Microsoft AEC Challenge数据集训练专业的回声消除模型,包括环境准备、数据清洗、模型架构设计、训练流程和实际部署注意事项。通过完整的代码示例和实战指南,帮助开发者快速掌握AEC技术,提升语音通信系统的回声消除效果。

weixin_27697385的博客 451

VTK学习笔记(一)——VTK环境配置及入门概念总结

VTK学习笔记(一)——VTK概述及相关环境配置 一、VTK环境配置 超好用的VTK环境配置,VTK8.2.0 + VS 2019 + Qt 5.14.0 + PCL 1.11.0 VTK源码,git地址 VTK在线帮助文档 二、VTK基本知识 1、VTK是什么? VTK的全称是Visualization Toolkit,即可视化工具包,它是一个开源、跨平台、可自由获取、支持并行处理的图形应用函数库。 2、VTK能做什么? 三维计算机图形、图像处理及可视化是VTK主要的应用方向。通过VTK可以根据许多学科

qq_36770651的博客 2365

Windows11下QGIS 3.34.4安装Geo-SAM插件全流程(附RTX3060 CUDA12.0配置技巧)

本文详细介绍了在Windows 11系统中为QGIS 3.34.4安装和配置Geo-SAM插件的完整流程,特别针对RTX 3060显卡用户提供了CUDA 12.0与PyTorch环境的精准搭建方案。通过预编码与交互式分割两大核心步骤,该插件能显著提升遥感图像半自动标注的效率,降低硬件门槛,是地理信息处理领域融合AI技术的实用指南。

weixin_29089057的博客 289

继续学习VTK

为了火车站的那个项目,学习VTK的进度停了两个多月,总算这些天空下来了,再次拾起VTK。由于是第一次接触VTK,以前对OpenGL也不是很熟,所以到处寻找各种教程,没办法,官方提供的教程要好几十美元,电子版又怎么也找不到,只好到处找有没有关于VTK的论坛,可惜啊,国内似乎没有一个专门的VTK论坛,偶尔找到几篇关于VTK的帖子,也大多介绍一下什么是VTK,怎么安装云云。看来一切学习只能靠自己了。。目

1万+

蜻蜓fm爬虫python

本文介绍了一个用于下载蜻蜓FM音频书籍的Python脚本实现。该脚本主要功能包括:1)通过账号密码登录获取认证信息;2)从目标书籍主页提取版本信息;3)获取书籍节目总数和分页信息;4)生成节目下载链接(使用HMAC-MD5加密算法生成请求签名);5)下载音频文件并保存。脚本采用多种反爬措施:设置User-Agent模拟浏览器行为、使用动态时间戳、HMAC-MD5签名验证等,有效规避简单的反爬机制。整个流程包括登录认证、获取书籍信息、生成下载链接和保存音频文件四个步骤,实现自动化批量下载功能。

野猫炫的博客 907

告别二极管发热!手把手教你用MOS管搭建同步整流电路(附死区时间设置避坑指南)

本文详细介绍了如何利用MOS管搭建同步整流电路(SR),以替代传统二极管,显著降低导通损耗和发热问题。内容涵盖自驱动方案的选择、关键元件参数计算、PCB布局要点及死区时间设置技巧,帮助工程师优化电源设计效率。

weixin_29540599的博客 443

【VTK】VTK(Visualization Toolkit)介绍及学习路线

VTK开源的跨平台可视化库,专注于2D/3D图形、图像处理和科学计算可视化

weixin_43510208的博客 3444

数据库系统概论课后习题答案(第五版 王珊、萨师煊)

第1章 绪论 1 .试述数据、数据库、数据库系统、数据库管理系统的概念。 答: ( l )数据( Data ) :描述事物的符号记录称为数据。数据的种类有数字、文字、图形、图像、声音、正文等。数据与其语义是不可分的。解析在现代计算机系统中数据的概念是广义的。早期的计算机系统主要用于科学计算,处理的数据是整数、实数、浮点数等传统数学中的数据。现代计算机能存储和处理的对象十分广泛,表

早知晓的博客 11万+

VTK简单实例学习(1)

在这里要特别感谢东灵工作室系列VTK教程。 因为项目需要,最近一直在自学VTK。将一些学习笔记、心得记录下来。 配上东灵工作室VTK教程链接。 一、VS2019 +VTK8.2+cmake-3.15.0-rc3-win64-x64 环境配置 参考我的另一篇blog环境配置教程 二、VS2019 编译VTK数据库 东灵工作室系列教程,均是用CMake ,我更喜欢直接用VS编译VTK案例,就是不使用C...

Emily_Buffy的博客 2144

用 SAML 2.0 Bearer Assertion 配置 ABAP OAuth 2.0 令牌交换

摘要: SAP系统集成中,身份跨系统传递是关键挑战。OAuth 2.0的SAML 2.0 Bearer Assertion grant机制通过SAML断言换取访问令牌,实现安全身份传递。配置核心在ABAP的SOAUTH2事务码,需绑定可信SAML身份提供商(IdP)并指定访问范围。实际应用中,需确保SSL加密传输,正确配置SAML IdP信任关系,并为OAuth客户端分配专用系统用户。常见问题包括证书不匹配、权限配置不当等,需分层控制权限边界以保障安全。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 829

微信小程序:使用mqtt手机屏幕锁屏后导致中断问题,让mqtt在手机黑屏后依然能保持连接及持续后台运行接收或处理任务,详解微信小程序MQTT在应用退到后台或手机熄屏的情况下自动检测并重连【强制保活】

微信小程序切后台后MQTT连接无法维持,微信小程序MQTT一旦用户锁屏、切换到后台或手机熄屏,连接就会断开,导致无法继续监听和处理业务消息,微信小程序mqtt保活方案,微信小程序屏幕锁屏或息屏导致mqtt连接中断怎么办,如何解决MQTT不能黑屏持续连接的问题,微信小程序应用退到后台 MQTT连接断开问题解决,苹果ios手机,安卓手机,uniapp微信小程序mqtt断开怎么解决,后台应用怎么保活,uni-app中MQTT连接频繁断开如何解决?应用退到后台后MQTT连接断开以及常连接断连的问题,微信小程序、MQ

✅ 精选推荐文章 3022
上一篇: opencv-4.5.3 + opencv_contrib-4.5.3 + vtk-9.0.3编译(全流程)
下一篇: 深度学习一(PyTorch物体检测实战)
扑腾的菜鸟
博客等级 码龄6年 2689粉丝 28原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

扑腾的菜鸟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值