OpenCV的viz库学习(二)

本文介绍如何利用OpenCV的Viz3d模块进行三维空间中的位姿计算与可视化,包括使用makeTransformToGlobal计算位姿、makeCameraPose和Viz3d::setViewerPose的使用方法,以及通过轴和视锥显示可视化相机位置的技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

学习目标

这次学习中将学会下面三部分:

  • 如何使用makeTransformToGlobal计算位姿
  • 如何使用makeCameraPose和Viz3d :: setViewerPose
  • 如何通过轴和视锥显示可视化相机位置

代码

#include <opencv2/viz.hpp>
#include <iostream>
#include <fstream>
using namespace cv;
using namespace std;
static void help()
{
    cout
    << "--------------------------------------------------------------------------"   << endl
    << "This program shows how to use makeTransformToGlobal() to compute required pose,"
    << "how to use makeCameraPose and Viz3d::setViewerPose. You can observe the scene "
    << "from camera point of view (C) or global point of view (G)"                    << endl
    << "Usage:"                                                                       << endl
    << "./transformations [ G | C ]"                                                 << endl
    << endl;
}
static Mat cvcloud_load()
{
    Mat cloud(1, 1889, CV_32FC3);
    ifstream ifs("bunny.ply");
    string str;
    for(size_t i = 0; i < 12; ++i)
        getline(ifs, str);
    Point3f* data = 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;
    cloud *= 5.0f;
    return cloud;
}
int main(int argn, char **argv)
{
    help();
    if (argn < 2)
    {
        cout << "Missing arguments." << endl;
        return 1;
    }
    bool camera_pov = (argv[1][0] == 'C');
    viz::Viz3d myWindow("Coordinate Frame");
    myWindow.showWidget("Coordinate Widget", viz::WCoordinateSystem());
    Vec3f cam_pos(3.0f,3.0f,3.0f), cam_focal_point(3.0f,3.0f,2.0f), cam_y_dir(-1.0f,0.0f,0.0f);
    Affine3f cam_pose = viz::makeCameraPose(cam_pos, cam_focal_point, cam_y_dir);
    Affine3f transform = viz::makeTransformToGlobal(Vec3f(0.0f,-1.0f,0.0f), Vec3f(-1.0f,0.0f,0.0f), Vec3f(0.0f,0.0f,-1.0f), cam_pos);
    Mat bunny_cloud = cvcloud_load();
    viz::WCloud cloud_widget(bunny_cloud, viz::Color::green());
    Affine3f cloud_pose = Affine3f().translate(Vec3f(0.0f,0.0f,3.0f));
    Affine3f cloud_pose_global = transform * cloud_pose;
    if (!camera_pov)
    {
        viz::WCameraPosition cpw(0.5); // Coordinate axes
        viz::WCameraPosition cpw_frustum(Vec2f(0.889484, 0.523599)); // Camera frustum
        myWindow.showWidget("CPW", cpw, cam_pose);
        myWindow.showWidget("CPW_FRUSTUM", cpw_frustum, cam_pose);
    }
    myWindow.showWidget("bunny", cloud_widget, cloud_pose_global);
    if (camera_pov)
        myWindow.setViewerPose(cam_pose);
    myWindow.spin();
    return 0;
}

注释

  • 创建一个可视化窗口
viz::Viz3d myWindow("Transformations");
  • 从摄像机位置,摄像机焦点和y方向获取摄像机位姿
Point3f cam_pos(3.0f,3.0f,3.0f), cam_focal_point(3.0f,3.0f,2.0f), cam_y_dir(-1.0f,0.0f,0.0f);
Affine3f cam_pose = viz::makeCameraPose(cam_pos, cam_focal_point, cam_y_dir);
  • 知道了相机坐标系轴获取变换矩阵
Affine3f transform = viz::makeTransformToGlobal(Vec3f(0.0f,-1.0f,0.0f), Vec3f(-1.0f,0.0f,0.0f), Vec3f(0.0f,0.0f,-1.0f), cam_pos);
  • 从bunny.ply文件创建云部件
Mat bunny_cloud = cvcloud_load();
viz::WCloud cloud_widget(bunny_cloud, viz::Color::green());
  • 已知相机坐标系中的姿势,估计全局姿势
Affine3f cloud_pose = Affine3f().translate(Vec3f(0.0f,0.0f,3.0f));
Affine3f cloud_pose_global = transform * cloud_pose;
  • 如果将视点设置为全局视点,则可视化相机坐标系和视锥
if (!camera_pov)
{
    viz::WCameraPosition cpw(0.5); // Coordinate axes
    viz::WCameraPosition cpw_frustum(Vec2f(0.889484, 0.523599)); // Camera frustum
    myWindow.showWidget("CPW", cpw, cam_pose);
    myWindow.showWidget("CPW_FRUSTUM", cpw_frustum, cam_pose);
}
  • 使用估计的全局姿势可视化点云部件
myWindow.showWidget("bunny", cloud_widget, cloud_pose_global);
  • 如果将视点设置为相机的视点,则将查看者姿态设置为cam_pose
if (camera_pov)
    myWindow.setViewerPose(cam_pose);

结果

1、这是从摄像机的角度来看的结果

2、这是从全局角度来看的结果

### OpenCV 可视化模块特性与使用 #### 图像显示基础 OpenCV 提供了 `cv2.imshow()` 函数用于展示图像窗口。此函数接受两个参数:一个是窗口名称字符串;另一个是要显示的图像矩阵[^1]。 ```python import cv2 image = cv2.imread('example.jpg') cv2.imshow('Image Window', image) cv2.waitKey(0) # Wait indefinitely until a key is pressed cv2.destroyAllWindows() ``` #### 绘制几何形状和文本 除了简单的图像显示之外,还可以利用绘图函数来增强视觉效果。这些函数允许绘制线条、矩形、圆圈以及添加文字说明: - **画线**: 使用`cv2.line()` - **画矩形框**: 使用`cv2.rectangle()` - **画圆形标记**: 使用`cv2.circle()` - **写入文本标签**: 使用`cv2.putText()` ```python # Drawing shapes on images start_point = (50, 50) end_point = (200, 200) color = (255, 0, 0) # Blue color in BGR format thickness = 2 # Line thickness of 2 px cv2.line(image, start_point, end_point, color, thickness) top_left_corner = (100, 100) bottom_right_corner = (300, 300) rectangle_color = (0, 255, 0) # Green color in BGR format cv2.rectangle(image, top_left_corner, bottom_right_corner, rectangle_color, thickness) center_coordinates = (400, 400) radius = 30 circle_color = (0, 0, 255) # Red color in BGR format cv2.circle(image, center_coordinates, radius, circle_color, thickness) font = cv2.FONT_HERSHEY_SIMPLEX text_position = (50, 50) font_scale = 1 text_color = (255, 255, 255) # White text color line_type = 2 # Line type can be one of the following: LINE_4, LINE_8 or LINE_AA. cv2.putText(image,'Text Here!', text_position , font, font_scale,text_color,line_type) ``` #### 创建自定义图形界面 对于更复杂的交互需求,可以考虑集成其他GUI如Tkinter 或 PyQt 来构建完整的应用程序环境。然而,在某些情况下仅通过OpenCV本身也可以实现基本的鼠标事件处理机制,从而支持用户点击操作并响应特定行为。 ```python def draw_circle(event,x,y,flags,param): global drawing if event == cv2.EVENT_LBUTTONDOWN: drawing = True elif event == cv2.EVENT_MOUSEMOVE: if drawing == True: cv2.circle(img,(x,y),5,(255,255,255),-1) elif event == cv2.EVENT_LBUTTONUP: drawing = False cv2.circle(img,(x,y),5,(255,255,255),-1) drawing = False img = np.zeros((512,512,3), np.uint8) cv2.namedWindow('Drawing Board') cv2.setMouseCallback('Drawing Board',draw_circle) while(True): cv2.imshow('Drawing Board', img) k = cv2.waitKey(1) & 0xFF if k == ord('m'): mode = not mode elif k == 27: break cv2.destroyAllWindows() ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

负壹

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

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

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

打赏作者

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

抵扣说明:

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

余额充值