计算机视觉图像处理机器学习【免费下载链接】opencv_contrib项目地址https://gitcode.com/gh_mirrors/ope/opencv_contrib点击查看免费下载本篇技术指南以 opencv_contrib 仓库 viz 模块官方教程 为核心讲解如何通过继承viz::Widget3D、利用viz::WidgetAccessor桥接 VTK 渲染管线创建属于你自己的 3D 可视化控件Widget并将其显示在Viz3d可视化窗口中。读完本文你将掌握自定义 Widget 的四步通用套路——定义子类、构建 VTK 几何管线、注入 Actor、设置颜色并展示同时能读懂 viz 模块内置控件如 WLine、WSphere、WCloud的底层实现模式具备扩展任意自定义几何体的能力。前置背景viz 模块与 VTK 的关系opencv_contrib 的modules/viz是 OpenCV 的三维可视化模块它本身并不实现渲染引擎而是封装了 VTKVisualization Toolkit来负责真实的三维场景渲染。这一点从构建系统可以明确看到modules/viz/CMakeLists.txt 第 1~3 行直接声明if(NOT HAVE_VTK) ocv_module_disable(viz) endif()——即系统找不到 VTK 时viz 模块会被整体禁用后续链接阶段还会把VTK_LIBRARIES作为模块依赖第 38~46 行。因此使用本教程的前提是系统已安装 VTK 开发库编译 OpenCV 时通过 CMake 配置检测到 VTKHAVE_VTK为真若以静态库方式构建 OpenCV仓库还在 CMake 中做了与 VTK 内置依赖zlib/jpeg/png/tiff的冲突规避处理第 7~24 行。理解了渲染最终由 VTK 完成这一事实下面要介绍的自定义 Widget 机制就顺理成章了既然底层场景是 VTK 的渲染器Renderer与 Actor那么让用户自定义几何体的最直接方式就是允许用户构造一个 VTKvtkProp/vtkActor并塞进 OpenCV 的 Widget 外壳中——这正是WidgetAccessor存在的意义。Widget 体系与 WidgetAccessor 的桥梁作用在深入代码之前先理清 viz 模块中与 Widget 相关的类层次定义见 modules/viz/include/opencv2/viz/widgets.hppviz::Widget所有控件的基类支持从 PLY 文件创建Widget::fromPlyFile、渲染属性设置setRenderingProperty/getRenderingProperty以及控件类型互转cast_Wviz::Widget3D三维控件基类在 Widget 之上增加了位姿控制setPose/updatePose/getPose、几何变换applyTransform与颜色设置setColorviz::Widget2D二维控件基类如文字、图像覆盖层只有颜色设置接口viz::WidgetAccessor定义在 modules/viz/include/opencv2/viz/widget_accessor.hpp它是对外暴露的存取器仅有getProp(const Widget)与setProp(Widget, vtkSmartPointervtkProp)两个静态方法负责在 Widget 与底层 VTK Prop 之间建立关联。WidgetAccessor的实现非常精简见 modules/viz/src/widget.cppvtkSmartPointervtkProp cv::viz::WidgetAccessor::getProp(const Widget widget) { return widget.impl_-prop; } void cv::viz::WidgetAccessor::setProp(Widget widget, vtkSmartPointervtkProp prop) { widget.impl_-prop prop; }即每个Widget内部通过Impl不透明实现指针持有一个vtkSmartPointervtkProp。setProp就是把这个内部指针赋值成你构造好的 VTK Actor而getProp供 viz 内部取回该 Prop 交给 VTK 渲染器。在 modules/viz/src/vizimpl.cpp 中可以看到Viz3d::VizImpl::showWidget的实现它先vtkProp3D::SafeDownCast(WidgetAccessor::getProp(widget))取出 Actor应用位姿矩阵再renderer_-AddActor(...)加入渲染器并把 Prop 记录到widget_actor_map_中。也就是说只要你在自定义 Widget 里正确调用了setPropviz 就能自动完成后续的显示工作。核心步骤自定义 3D Widget 的完整流程原教程给出了创建自定义控件的一套固定流程本文将其展开为可复现的完整代码完整程序见 modules/viz/samples/creating_widgets.cpp。第一步扩展 Widget3D 定义新控件类class WTriangle : public viz::Widget3D { public: WTriangle(const Point3f pt1, const Point3f pt2, const Point3f pt3, const viz::Color color viz::Color::white()); };要点自定义类必须继承viz::Widget3D三维控件或viz::Widget2D二维控件构造函数接受三角形的三个三维顶点Point3f颜色参数带默认值viz::Color::white()几何数据在构造函数内构建这是自定义控件与内置控件保持一致的设计——内置的WLine、WSphere、WCube等同样是在构造函数中完成几何构造。第二步在构造函数内构建 VTK 几何管线并注入 Actor这一步是核心中的核心共分四个小环节几何点、拓扑连接、PolyData 数据对象、Mapper 与 Actor。WTriangle::WTriangle(const Point3f pt1, const Point3f pt2, const Point3f pt3, const viz::Color color) { // 1) 创建三个顶点 vtkSmartPointervtkPoints points vtkSmartPointervtkPoints::New(); points-InsertNextPoint(pt1.x, pt1.y, pt1.z); points-InsertNextPoint(pt2.x, pt2.y, pt2.z); points-InsertNextPoint(pt3.x, pt3.y, pt3.z); // 2) 定义三角形拓扑按索引 0、1、2 连接三个点 vtkSmartPointervtkTriangle triangle vtkSmartPointervtkTriangle::New(); triangle-GetPointIds()-SetId(0,0); triangle-GetPointIds()-SetId(1,1); triangle-GetPointIds()-SetId(2,2); vtkSmartPointervtkCellArray cells vtkSmartPointervtkCellArray::New(); cells-InsertNextCell(triangle); // 3) 打包为 vtkPolyData几何 拓扑 vtkSmartPointervtkPolyData polyData vtkSmartPointervtkPolyData::New(); polyData-SetPoints(points); polyData-SetPolys(cells); // 4) 创建 Mapper 与 Actor vtkSmartPointervtkPolyDataMapper mapper vtkSmartPointervtkPolyDataMapper::New(); #if VTK_MAJOR_VERSION 5 mapper-SetInput(polyData); // 老版本 VTK 接口 #else mapper-SetInputData(polyData); // VTK 6 及以上接口 #endif vtkSmartPointervtkActor actor vtkSmartPointervtkActor::New(); actor-SetMapper(mapper); // 5) 将 Actor 存入 Widget —— 这一步是自定义控件的关键 viz::WidgetAccessor::setProp(*this, actor); // 6) 设置颜色 —— 必须放在 setProp 之后 setColor(color); }这段代码逐层解释如下顶点数据vtkPoints依次插入三个点顺序对应调用者传入的pt1、pt2、pt3拓扑关系vtkTriangle通过GetPointIds()-SetId(...)声明三角形由第 0、1、2 号顶点构成再通过vtkCellArray把该单元注册进单元列表数据对象vtkPolyData同时持有几何SetPoints与拓扑SetPolys这是 VTK 渲染管线的输入数据单元Mapper 与 ActorvtkPolyDataMapper负责把 PolyData 转换为可绘制的图元vtkActor是场景中真正被渲染器处理的实体两者通过actor-SetMapper(mapper)绑定。注意代码里对VTK_MAJOR_VERSION 5做了分支处理——VTK 6 之后SetInput更名为SetInputData示例代码对两代 VTK 都做了兼容注入 Actorviz::WidgetAccessor::setProp(*this, actor)把 Actor 存入 Widget 内部指针这样Viz3d::showWidget才能通过getProp取回并交给 VTK 渲染器对应 modules/viz/src/vizimpl.cpp 中的取用逻辑设置颜色setColor(color)必须放在setProp之后因为Widget3D::setColor的实现modules/viz/src/widget.cpp内部要通过vtkActor::SafeDownCast(WidgetAccessor::getProp(*this))拿到 Actor 才能修改属性若在setProp之前调用Actor 还是空指针会触发CV_Assert断言失败。从setColor的源码可以看到颜色是如何被应用的先关闭 Mapper 的标量着色ScalarVisibilityOff()确保不使用顶点标量色再对 Actor 属性设置SetColor与SetEdgeColor同时决定面片与边线颜色最后actor-Modified()通知 VTK 重绘。第三步构造控件并显示在窗口中int main() { help(); /// 创建可视化窗口 viz::Viz3d myWindow(Creating Widgets); /// 创建一个三角形控件 WTriangle tw(Point3f(0.0,0.0,0.0), Point3f(1.0,1.0,1.0), Point3f(0.0,1.0,0.0), viz::Color::red()); /// 将控件显示到窗口中 myWindow.showWidget(TRIANGLE, tw); /// 启动事件循环 myWindow.spin(); return 0; }三个环节的说明窗口创建viz::Viz3d myWindow(Creating Widgets)创建名为 Creating Widgets 的三维可视化窗口Viz3d类定义于 modules/viz/include/opencv2/viz/viz3d.hpp控件展示myWindow.showWidget(TRIANGLE, tw)以字符串 ID TRIANGLE 注册该控件。showWidget的完整签名是void showWidget(const String id, const Widget widget, const Affine3d pose Affine3d::Identity())第三个参数允许你直接在展示时指定初始位姿默认单位变换。ID 用于后续getWidget/removeWidget/setWidgetPose等窗口级操作事件循环myWindow.spin()启动渲染与交互事件循环窗口保持打开并响应用户视角操作直到用户关闭窗口。示例中三个顶点取(0,0,0)、(1,1,1)、(0,1,0)颜色为红色viz::Color::red()最终在窗口中渲染出一个红色三角形。结果展示程序运行后窗口中会显示一个红色三角形如下图所示。用户可以通过鼠标自由旋转、缩放视角来观察该三角形在三维空间中的位置与朝向。源码印证内置控件也遵循同一套模式定义子类 → 构建 VTK 管线 → setProp → setColor并不是教程的孤例而是整个 viz 模块所有内置控件统一遵循的范式。可以从源码中找出大量同类实现几何体类modules/viz/src/shapes.cppWLine第 60~67 行、WSphere第 91~98 行、WArrow第 172~179 行、WCube第 332~339 行等控件全部以WidgetAccessor::setProp(*this, actor)收尾点云类modules/viz/src/clouds.cppWCloud第 91 行、WPaintedCloud第 159、201 行、WMesh第 492 行同样如此复合控件modules/viz/src/shapes.cppWCloudCollection::addCloud第 242 行与WWidgetMerger::addWidget第 497 行还会用vtkActor::SafeDownCast(WidgetAccessor::getProp(widget))取出已有控件的 Actor 做进一步组合这印证了getProp的另一个用途——读取并修改已有控件的底层 VTK 对象。值得注意的差异是内置几何控件构造后并未显式调用setColor而是在构造函数通过actor-GetProperty()设置颜色等属性而本教程的自定义控件把setColor作为对外接口这恰好演示了如何复用Widget3D::setColor这一现成能力。另外内置控件还会做一些渲染细节设置如BackfaceCullingOn()背面剔除、SetInterpolationToFlat()平面着色如果你需要类似效果可以在自己的构造器中通过vtkActor的 Property 直接配置。进阶自定义控件的渲染属性与后续操作控件创建并显示后还可以通过以下接口进一步控制外观与行为渲染属性Widget::setRenderingProperty(int property, double value)支持POINT_SIZE、OPACITY、LINE_WIDTH、FONT_SIZE、REPRESENTATION点/线框/面取值为REPRESENTATION_POINTS、REPRESENTATION_WIREFRAME、REPRESENTATION_SURFACE、SHADINGSHADING_FLAT/SHADING_GOURAUD/SHADING_PHONG、AMBIENT、LIGHTING等枚举定义于 modules/viz/include/opencv2/viz/widgets.hpp实现于 modules/viz/src/widget.cpp。其实现同样依赖getProp取出vtkActor后逐项映射到 VTK 属性位姿控制Widget3D::setPose/updatePose/getPose以及Viz3d::setWidgetPose/updateWidgetPose/getWidgetPose可以随时移动、旋转自定义控件颜色调整Widget3D::setColor与Widget2D::setColor分别支持三维、二维控件改色viz::Color预置了丰富的颜色工厂方法red()、green()、blue()、white()、orange()等见 modules/viz/include/opencv2/viz/types.hpp窗口级操作Viz3d::removeWidget(TRIANGLE)移除控件、getWidget(TRIANGLE)取回控件控件是隐式共享的修改返回对象会立即反映到窗口、spinOnce单步渲染、saveScreenshot保存截图等接口可参考 modules/viz/include/opencv2/viz/viz3d.hpp。注意事项与适用前提编译开关示例源码modules/viz/samples/creating_widgets.cpp用#ifndef USE_VTK做了兜底——若未定义USE_VTK宏程序只打印提示并退出。这意味着该示例需要直接与 VTK 一同编译教程原文说明在 OpenCV 构建系统中由ocv_add_samplesmodules/viz/CMakeLists.txt统一处理头文件自定义代码需要同时包含opencv2/viz.hpp与opencv2/viz/widget_accessor.hpp以及所需 VTK 头文件vtkPoints.h、vtkTriangle.h、vtkCellArray.h、vtkPolyData.h、vtkPolyDataMapper.h、vtkActor.h等类型匹配setProp期望vtkSmartPointervtkProp类型的参数vtkActor是其子类可直接传入反过来取用时应按 modules/viz/include/opencv2/viz/widget_accessor.hpp 的说明用vtkActor::SafeDownCast(viz::WidgetAccessor::getProp(widget))向下转型因为getProp返回的是基类指针API 状态viz 模块头文件modules/viz/include/opencv2/viz/viz3d.hpp保留了 beta 声明提示该模块 API 仍处不稳定阶段、不保证二进制兼容升级 OpenCV/VTK 版本时需留意接口变化依赖环境所有自定义控件功能都建立在系统具备 VTK 且 viz 模块成功编译的前提下若构建时未检测到 VTKHAVE_VTK为假viz 模块及本示例都不会被编译。扩展阅读教程同系列prev_tutorial{tutorial_transformations}三维变换、next_tutorial{tutorial_histo3D}直方图三维可视化与 creating_widgets.markdown 构成 viz 模块教程链viz 模块其余教程位于 modules/viz/tutorials涵盖轨迹可视化、SLAM 场景重建等应用更多示例程序见 modules/viz/samples其中不少展示了WidgetAccessor与自定义控件的实际用法。通过本指南你已经掌握了 viz 模块自定义控件从类定义、VTK 管线构建、Actor 注入到窗口展示的完整链路——这正是把任意自定义三维几何三角形、网格、点云乃至复合体接入 OpenCV 可视化场景的标准方法。赞分享计算机视觉图像处理机器学习【免费下载链接】opencv_contrib项目地址https://gitcode.com/gh_mirrors/ope/opencv_contrib点击查看免费下载相关推荐OpenCV viz 模块自定义 Widget 开发指南基于 WidgetAccessor 与 VTK 构建 3D 可视化控件OpenCV viz 模块自定义 Widget 开发指南基于 WidgetAccessor 与 VTK 构建 3D 可视化控件 导读 在 OpenCV 的扩展计算机视觉图像处理深度学习机器学习学之思xzs系统分布式ID生成雪花算法与数据库自增对比学之思xzs系统分布式ID生成雪花算法与数据库自增对比 学之思xzs作为一款在线考试系统在处理大量考试数据和用户信息时高效可靠的ID生成机制至关重要。本文教育后端前端小程序OpenCV Viz 三维可视化实战从窗口启动、控件位姿控制到自定义控件与 3D 直方图OpenCV Viz 三维可视化实战从窗口启动、控件位姿控制到自定义控件与 3D 直方图 导读 本文以 opencv_contrib 仓库中 viz 模块教计算机视觉图像处理深度学习机器学习上一篇AgentScope 2.0完整指南如何构建生产级多智能体系统下一篇大麦抢票自动化ticket-purchase 三步跑通实战创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
企业数字化 ERP 产品动态
相关推荐
RisingWave 开发者文档体系:构建 rustdoc 索引页与核心 crate 导航指南 数据库流处理后端数据工程 【免费下载链接】risingwave Event streaming platform for agentic AI. Continuously ingest, transform, and serve event streams in real time, at scale. 项目地址: https://gitcode.com/gh_mirrors/ri/risingwave 点击查看 免费下载… · 2026/9/25 3:30:49
苹果CMS+油条视频模板视频站搭建全攻略:从宝塔部署到上线备份 简介:油条视频是一套基于苹果CMS系统的视频建站完整解决方案,面向需要快速搭建影视资源站的站长、运营者及PHP二次开发学习者。系统后台内置自定义参数,可灵活对应会员升级与积分充值页面;视频、演员、专题、收藏、会员等模块齐全… · 2026/9/25 3:30:49
OpenTTD 编译实战:依赖库、CMake 构建流程与 Windows/多平台调试选项 游戏开发 【免费下载链接】OpenTTD OpenTTD is an open source simulation game based upon Transport Tycoon Deluxe 项目地址: https://gitcode.com/gh_mirrors/op/OpenTTD 点击查看 免费下载 OpenTTD(基于 Transport Tycoon Deluxe 的开源运输模拟游… · 2026/9/25 3:30:49
ESP32 轻量应用平台:基于 LittleFS 与 JSON 实现应用即目录 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 4:58:03
C++ Primer高清PDF下载指南:版本选择、质量判断与高效学习路线 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 4:58:02
AD620+LM358小信号采集电路:从原理到PCB布局的工程实践 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 4:58:02
S32K ADC寄存器深度解析与DMA协同优化 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 4:58:02
Ozone嵌入式调试原理:硬件级追踪与RTOS深度分析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 4:58:02
GDS版图从入门到精通:层次结构、生成流程与-uniquifycellnames避坑指南 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 4:57:55
创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31
MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:37