开发环境:Ubuntu 18.04 LTS + ROS Melodic + ViSP 3.3.1
文章内容主要参考ViSP官方教学文档:https://visp-doc.inria.fr/doxygen/visp-daily/tutorial_mainpage.html

 本文介绍了如何使用ViSP计算平面图像的投影,我们在空间中放置一个正方形,通过投影计算在空间中不同位置观察这个正方形时,所呈现图像的形状。本文主要参考了simulator中的tutorial-image-simulator.cpp例程。首先要获取这个例程文件并编译它

svn export https://github.com/lagadic/visp.git/trunk/tutorial/simulator/image

这里要注意,如果之前下载过image例程文件的同学,这里可能会报错,因为有两个image同名文件夹,可以把之前的image重命名一下。

mkdir -p image/build
cd image/build
cmake .. -DCMAKE_BUILD_TYPE=Release -DVISP_DIR=$VISP_WS/visp-build
make tutorial-image-simulator.cpp

 编译完成后即可运行观察结果

./tutorial-image-simulator

在这里插入图片描述

下面介绍一下代码实现过程

#include <visp3/gui/vpDisplayGDI.h>
#include <visp3/gui/vpDisplayOpenCV.h>
#include <visp3/gui/vpDisplayX.h>
#include <visp3/io/vpImageIo.h>
//! [Include]
#include <visp3/robot/vpImageSimulator.h> //导入ImageSimulator头文件
//! [Include]

int main()
{
  try {
    //! [Read image]
    vpImage<unsigned char> target; //新建一个图像容器
    vpImageIo::read(target, "./target_square.pgm");
     //从文件中读入原始图像,即一个20*20的正方形,带有四个圆点
    //! [Read image]

    //! [Set model]
    vpColVector X[4]; //新建数组储存原始图像的位置
    for (int i = 0; i < 4; i++)
      X[i].resize(3); //把一维数组变形为3*4的二维数组
    // Top left     Top right       Bottom right   Bottom left
    X[0][0] = -0.1; //正方形左上角顶点的X轴坐标
    X[1][0] = 0.1;  //正方形右上角顶点的X轴坐标
    X[2][0] = 0.1;  //正方形左下角顶点的X轴坐标
    X[3][0] = -0.1;  //正方形右下角顶点的X轴坐标
    X[0][1] = -0.1;  //正方形左上角顶点的y轴坐标
    X[1][1] = -0.1;  //正方形右上角顶点的y轴坐标
    X[2][1] = 0.1;  //正方形左下角顶点的y轴坐标
    X[3][1] = 0.1;  //正方形右下角顶点的y轴坐标
    X[0][2] = 0;  //正方形左上角顶点的z轴坐标
    X[1][2] = 0;  //正方形右上角顶点的z轴坐标
    X[2][2] = 0;  //正方形左下角顶点的z轴坐标
    X[3][2] = 0;  //正方形右下角顶点的z轴坐标
    //! [Set model]

    //! [Image construction]
    vpImage<unsigned char> I(480, 640); //新建图像容器,用于储存映射后的图像
    //! [Image construction]
    //! [Camera parameters]
    vpCameraParameters cam(840, 840, I.getWidth() / 2, I.getHeight() / 2); 
    //设置相机内部参数(前两个参数表示图像的尺寸,后两个参数表述原点位置)
    //! [Camera parameters]
    //! [Set cMo]
    vpHomogeneousMatrix cMo(0, 0, 0.35, 0, vpMath::rad(30), vpMath::rad(15));
    //设置相机和目标物体之间的变换矩阵,前三个参数表示平移参数,后三个参数表示旋转参数
    //! [Set cMo]

    //! [Create simulator]
    vpImageSimulator sim; //新建一个仿真容器
    sim.setInterpolationType(vpImageSimulator::BILINEAR_INTERPOLATION); //设置插值方式为双线性插值
    sim.init(target, X); //初始化目标位置
    //! [Create simulator]

    // Get the new image of the projected planar image target
    //! [Render image]
    sim.setCleanPreviousImage(true); //清除仿真器中原有图像
    sim.setCameraPosition(cMo); // 根据变换矩阵设置相机位置
    sim.getImage(I, cam); //获取当前位置下的图像并储存在图像容器I中
    //! [Render image]
    // 保存图像
    //! [Write image]
    try {
      vpImageIo::write(I, "./rendered_image.jpg");
    } catch (...) {
      std::cout << "Unsupported image format" << std::endl;
    }
//! [Write image]

#if defined(VISP_HAVE_X11)
    vpDisplayX d(I);
#elif defined(VISP_HAVE_GDI)
    vpDisplayGDI d(I);
#elif defined(VISP_HAVE_OPENCV)
    vpDisplayOpenCV d(I);
#else
    std::cout << "No image viewer is available..." << std::endl;
#endif
    // 显示图像
    vpDisplay::setTitle(I, "Planar image projection");
    vpDisplay::display(I);
    vpDisplay::flush(I);
    std::cout << "A click to quit..." << std::endl;
    vpDisplay::getClick(I);
  } catch (const vpException &e) {
    std::cout << "Catch an exception: " << e << std::endl;
  }
}

如果大家对于深度学习与计算机视觉领域感兴趣,希望获得更多的知识分享与最新的论文解读,欢迎关注我的个人公众号“深视”。

在这里插入图片描述