前言
该文章主要是记录了如何利用opencv中的viz来进行三维点云建模。由于目前遇到了需要建立三维地图和地图场景加载的需求,故在此记录。编译环境为opencv3.4.1,vtk7.1.1,语言标准为C++11。
一、环境配置
打开VS工程,右击属性进行VC++目录的包含目录、库目录以及链接器->输入->附加依赖项配置。具体配置可以参考其它博主的博客,一般配置包含目录、库目录和链接器中的附件依赖项环境基本就可以正常运行。
二、具体实现
1.头文件
头文件代码如下:
#include<iostream>
#include <fstream>
#include <vector>
#include <cmath>
#include <algorithm>
#include <string>
#include <opencv2/opencv.hpp>
#include <opencv2/viz.hpp>
2.代码
在进行代码实现前,先对数据进行一部分定义,假定光学地图的tif文件为三通道,变量值为无符号char型(及值为0-255);假定高程信息为float类型。光学地图和高程信息覆盖的经纬度范围相同(分辨率不同可以后期进行双三插值)。
int main(){
std::string filepath = "E:\\weitu\\光学地体.tif";//光学地图为三通道tif文件(RGB通道),文件数据类型为unsigned char
std::string DEM_filepath = "E:\\weitu\\DEM.tif";//高程信息,文件数据为float类型
cv::Mat image = cv::imread(filepath, cv::IMREAD_UNCHANGED);//像素为BGR
cv::Mat DEM_data = cv::imread(DEM_filepath, CV_LOAD_IMAGE_ANYDEPTH);//DEM数据,两种数据imread的第二个参数有所区别
float minValue = *std::min_element(DEM_data.begin<float>(), DEM_data.end<float>());//取高程最小值
cv::Size newSize(image.cols, image.rows);
cv::resize(DEM_data, DEM_data, newSize, 0, 0, cv::INTER_CUBIC);//插值和影像分辨率统一
std::vector<cv::Vec3f> cloud;
std::vector<cv::Vec3b> color;
int inter_ = 2;//采样间隔
for (long long y = 0; y < nImgSizeY; y+= inter_) {
for (long long x = 0; x < nImgSizeX; x+= inter_) {
cloud.emplace_back(cv::Vec3f(y / inter_, x / inter_, (DEM_data.at<float>(y, x) - minValue) * 5));//经纬高,第三个元素*5是防止高程变化平缓,人工可调的系数
color.emplace_back(image.at<cv::Vec3b>(y,x));//BGR值
}
}
cv::viz::WCloud cloud_widget(cloud, color);//点云
cv::viz::Viz3d window("window");
cloud_widget.setRenderingProperty(cv::viz::RenderingProperties::POINT_SIZE, 2);//设置点大小
window.showWidget("pnt_cloud", cloud_widget);//窗口显示点云,ID为pnt_cloud
//下面是加入长方体并设置RGB轮换变化
cv::viz::WCube cube_widget(cv::Point3f(51.0, -15, 0.0), cv::Point3f(5.0, 0.5, 15), true, cv::viz::Color::red());
cube_widget.setRenderingProperty(cv::viz::LINE_WIDTH, 1.0); // 设置线条粗细
//cube_widget.setRenderingProperty(cv::viz::OPACITY, 0.1);//设置透明度
window.showWidget("Cube", cube_widget);
const int delay = 100; // 单位1毫秒的延迟
int aa = 0;
//上面部分
//接下来开始显示
while (!window.wasStopped()) {
// 处理事件
window.spinOnce(delay, true);
if (aa % 3 == 0) {
cube_widget.setColor(cv::viz::Color::blue());
}
if (aa % 3 == 1) {
cube_widget.setColor(cv::viz::Color::red());
}
if (aa % 3 == 2) {
cube_widget.setColor(cv::viz::Color::green());
}
++aa;
}
image.release();//释放内存
DEM_data.release();
}
总结
下面看一看效果图
初步尝试,有好的建议和问题都可以提出。