子图
实际用于SLAM点云信息的可视化时,希望能够实现同时显示相机当前图像信息以及特征点跟踪。此时就需要构建子图对象,展示点云信息的同时显示其余信息。
构建子图对象
构建子图对象如下:
pangolin::View& sub_viewer = pangolin::Display(const std::string& name)
.SetBounds(Attach bottom, Attach top, Attach left, Attach right, double aspect)
.SetLock(Lock horizontal, Lock vertical );
name
:视图或子图的名称SetBounds
:用于设置子图的位置,同交互视图相同SetLock
:设置子图锁定位置,当缩放视窗时,将自动锁定子图至规定位置horizontal
:水平锁定位置,选填如下内容:LockLeft
:左侧LockCenter
:中央LockRight
:右侧
vertical
:垂直锁定位置,选填如下内容:LockBottom
:底部LockCenter
:中央LockTop
:顶部
图像容器
对于子图要展示的图像内容,应先创建容器用于装载:
pangolin::GlTexture imgTexture(GLint width, GLint height, GLint internal_format, bool sampling_linear, int border, GLenum glformat, GLenum gltype, GLvoid* data )
width、height
:装载的图像宽度、高度,同被装载的图像宽度、高度一致internal_format
:Pangolin内部图像存储格式,一般默认填写GL_RGB
sampling_linear
:是否开启现行采样,默认填写false
border
:边界大小(像素),默认填写0
glformat
:GL图像存储格式,一般采用OpenCV进行读取图像,故而填写GL_BGR
gltype
:GL图像数据格式,OpenCV中格式为UInt
类型,故而填写GL_UNSIGNED_BYTE
data
:GL图像数据
装载图像
将图像信息装载至容器
imgTexture.Upload(const void* data, GLenum data_format, GLenum data_type)
data
:图像数据data_format
:图像存储格式data_type
:图像数据格式
显示子图
最后,显示子图信息
// 激活子图
sub_viewer.Activate();
// 子图背景色设置
glColor3f(1.0f, 1.0f, 1.0f);
// 反转Y轴,否则输出是倒着的
imgTexture.RenderToViewportFlipY();
此处,由于视图原点位置左下角,而OpenCV原点位于左上角,故而需要反转Y轴。
综合:子图显示
综上所述,构建子图的全体流程如下:
CMake
由于使用了OpenCV库,需要引入CV库:
根目录下CMakeLists.txt文件如下:
# cmake version
cmake_minimum_required(VERSION 3.21)
# project name
project(Study)
# cpp version
set(CMAKE_CXX_STANDARD 14)
# eigen
include_directories("/usr/include/eigen3")
# Sophus
find_package(Sophus REQUIRED)
include_directories(${Sophus_INCLUDE_DIRS})
# pangolin
find_package(Pangolin REQUIRED)
include_directories(${Pangolin_INCLUDE_DIRS})
# opencv
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
# incldue
include_directories(include)
# src
add_subdirectory(src)
src下CMakeLists.txt文件如下:
# exec
add_executable(Study main.cpp)
# link pangolin
target_link_libraries(Study ${Pangolin_LIBRARIES})
# link opencv
target_link_libraries(Study ${OpenCV_LIBRARIES})
头文件
Include下头文件main.h如下:
#ifndef STUDY_MAIN_H
#define STUDY_MAIN_H
#include <iostream>
#include <cmath>
#include <unistd.h>
// Eigen
#include <Eigen/Core>
#include <Eigen/Dense>
#include <Eigen/Geometry>
// Sophus
#include <sophus/so3.hpp>
#include <sophus/se3.hpp>
// Pangolin
#include <pangolin/pangolin.h>
// OpenCV
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
// namespace
using namespace std;
using namespace Eigen;
#endif //STUDY_MAIN_H
源代码
src下源文件main.cpp如下:
#include <string>
#include <iostream>
#include "main.h"
int main()
{
/*-------- Pangolin相机 --------*/
// 视窗
pangolin::CreateWindowAndBind("MultiImage", 752, 480);
// 启动深度测试
glEnable(GL_DEPTH_TEST);
// 相机
pangolin::OpenGlRenderState s_cam(
pangolin::ProjectionMatrix(752, 480, 420, 420, 320, 320, 0.1, 1000),
pangolin::ModelViewLookAt(-2, 0, -2, 0, 0, 0, pangolin::AxisY)
);
/*-------- 视图、子图 --------*/
// 主视图cam,拉伸
pangolin::View& d_cam = pangolin::Display("cam")
.SetBounds(0., 1., 0., 1., -752/480.)
.SetHandler(new pangolin::Handler3D(s_cam));
// 子图1 image_1,裁剪,锁定左上角
pangolin::View& cv_img_1 = pangolin::Display("image_1")
.SetBounds(2/3.0f, 1.0f, 0., 1/3.0f, 752/480.)
.SetLock(pangolin::LockLeft, pangolin::LockTop);
// 子图2 image_2,裁剪,锁定右下角
pangolin::View& cv_img_2 = pangolin::Display("image_2")
.SetBounds(0., 1/3.0f, 2/3.0f, 1.0, 752/480.)
.SetLock(pangolin::LockRight, pangolin::LockBottom);
// glTexture容器,用于读取图像
pangolin::GlTexture imgTexture1(752, 480, GL_RGB, false, 0, GL_BGR, GL_UNSIGNED_BYTE);
pangolin::GlTexture imgTexture2(752, 480, GL_RGB, false, 0, GL_BGR, GL_UNSIGNED_BYTE);
while(!pangolin::ShouldQuit()){
// 清空颜色、深度缓存区
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// 背景色
glClearColor(0.2, 0.2, 0.2, 0.3);
// 激活相机
d_cam.Activate(s_cam);
/*-------- 绘制主视图内容 --------*/
// 原点立方体
glColor3f(1.0f, 1.0f, 1.0f);
pangolin::glDrawColouredCube();
/*-------- 子图信息 --------*/
// 读取图像
cv::Mat img1 = cv::imread("/home/jasonli/workspace/Study/pic/01.png");
cv::Mat img2 = cv::imread("/home/jasonli/workspace/Study/pic/02.png");
// 装载图像
imgTexture1.Upload(img1.data, GL_BGR, GL_UNSIGNED_BYTE);
imgTexture2.Upload(img2.data, GL_BGR, GL_UNSIGNED_BYTE);
/*-------- 子图1配置 --------*/
// 激活子图1
cv_img_1.Activate();
// 子图1背景色设置
glColor3f(1.0f, 1.0f, 1.0f);
// 反转Y轴,否则输出是倒着的
imgTexture1.RenderToViewportFlipY();
/*-------- 子图2配置 --------*/
// 激活子图2
cv_img_2.Activate();
// 子图1背景色设置
glColor3f(1.0f, 1.0f, 1.0f);
// 反转Y轴,否则输出是倒着的
imgTexture2.RenderToViewportFlipY();
// 帧循环
pangolin::FinishFrame();
}
return 0;
}
效果如下: