三维重建KInectFusion 学习笔记
目录
KInectFusion实战笔记 有icp
步骤和条件:
从零开始复现实时三维重建KInectFusion
KInectFusion实战笔记 有icp
KinectFusion实战笔记_kinectfusion python_Stefanie_Song的博客-CSDN博客
GitHub - JingwenWang95/KinectFusion: KinectFusion implemented in Python with PyTorch
步骤和条件:
1.下载数据:freiburg1_desk
2.执行dataset/preprocess.py
然后可以执行kinfu_gui.py
除了重建必要的深度图和彩色图之外,TUM数据集也包含相机轨迹的groundtruth,即在一个固定坐标系下,每一帧图像拍摄时相机的位置和方向坐标。
原文链接:https://blog.csdn.net/weixin_43272109/article/details/127099847
需要rgb图,深度图,
depth.txt和groundtruth.txt
实时三维重建KInectFusion c++
一,从零开始复现实时三维重建KInectFusion
实时三维重建算法
【[本文代码](https://github.com/sky3139/KinectFusion_2022)】
准备环境
准备数据集
检查数据集
计算相机坐标系下的点云
创建一个Patch管理GPU的2D内存
TSDF类
修改后的主函数
最后效果如下
实时三维重建算法
静态:
知乎:三维重建 3D reconstruction 有哪些实用算法?
【本文代码】
准备环境
我们对Markdown编辑器进行了一些功能拓展与语法支持,除了标准的Markdown编辑器功能,我们增加了如下几点新功能,帮助你用它写博客:
OpenCV: 加上viz编译 ,方便可视化 其他类似的可视化工具 pangolin opengl pcl qglviewer vtk open3d等;
CUDA 8.0 以上 KinectFusion 的复现工作大多基于cuda8.0 在ubuntu20.04 上难以工作,本次复现采用较新的api;
准备数据集
TUM数据集,这里以 f3_long_office为例子
将深度图和RGB图时间同步(后期更新此工具)
检查数据集
#include "read.hpp"
using namespace std;
int main()
{DataSet<float> dt("/home/lei/dataset/paper/f3_long_office");for (int i = 0; i < dt.pose.frames; i++){cv::Mat rgb = cv::imread(dt.color_path[i]);cv::Mat depth = cv::imread(dt.depth_path[i]);cv::imshow("rgb", rgb);cv::imshow("depth", depth);cv::waitKey(1);}
}
能正确读取rgb图和深度图即可
计算相机坐标系下的点云
定义一个内参结构体
struct Intr
{
union
{
float4 cam;
struct
{
float fx, fy, cx, cy;
};
};
Intr(float4 intr)
{
cam = intr;
}
__device__ inline float3 cam2world(int u, int v, float z)
{
// TODO 这里可预先计算fx,fy倒数,然后计算乘法,应该会快一些
float x = __fdividef(z * (u - cx), fx);
float y = __fdividef(z * (v - cy), fy);
return make_float3(x, y, z);
}
};
深度图转点云的cuda核函数
__global__ void depth2cam(uint16_t *hd_depth_ptr, float3 *output, Intr intr)
{
int tx = threadIdx.x; // 640
int ty = blockIdx.x; // 480
int rawidx = tx + ty * 640;
float pz = hd_depth_ptr[rawidx] * 0.0002f; //深度转换为米
output[rawidx] = intr.cam2world(tx, ty, pz);
}
main中
int main()
{DataSet<float> dt("/home/lei/dataset/paper/f3_long_office");ck(cudaGetLastError());Intr intr(make_float4(550, 550, 320, 240));cv::viz::Viz3d window("map");window.showWidget("Coordinate", cv::viz::WCoordinateSystem());for (int i = 0; i < dt.pose.frames; i++){cv::Mat rgb = cv::imread(dt.color_path[i]);cv::Mat depth = cv::imread(dt.depth_path[i], cv::IMREAD_ANYDEPTH);uint16_t *hd_depth_ptr;cudaMallocManaged((void **)&hd_depth_ptr, depth.rows * depth.cols * sizeof(uint16_t));cudaMemcpy(hd_depth_ptr, depth.ptr<uint16_t>(), depth.rows * depth.cols * sizeof(uint16_t), cudaMemcpyHostToDevice);float3 *cloud;cudaMallocManaged(&cloud, depth.rows * depth.cols * sizeof(float3));depth2cam<<<depth.rows, depth.cols>>>(hd_depth_ptr, cloud, intr);ck(cudaDeviceSynchronize());cv::Mat cpu_cloud(depth.rows * depth.cols, 1, CV_32FC3);cudaMemcpy(cpu_cloud.ptr<float *>(), cloud, depth.rows * depth.cols * sizeof(float3), cudaMemcpyDeviceToHost);cv::Mat dst2 = rgb.reshape(3,640 * 480);window.showWidget("depthmode", cv::viz::WCloud(cpu_cloud, dst2));window.spinOnce(true);window.spin();cv::imshow("rgb", rgb);cv::imshow("depth", depth);cv::waitKey(1);cudaFree(hd_depth_ptr);cudaFree(cloud);}
}
运行结果如下
创建一个Patch管理GPU的2D内存
template <class T>
struct Patch
{
T *devPtr;
size_t pitch = 0;
size_t rows, cols;
Patch()
{
}
Patch(int rows, int cols) : rows(rows), cols(cols)
{
ck(cudaMallocPitch((void **)&devPtr, &pitch, cols * sizeof(T), rows));
ck(cudaMemset2D(devPtr, pitch, 0, sizeof(T) * cols, rows));
// std::cout << pitch << " " << sizeof(T) * cols << std::endl;
}
void creat(const int rows, const int cols)
{
this->rows = rows;
this->cols = cols;
ck(cudaMallocPitch((void **)&devPtr, &pitch, cols * sizeof(T), rows));
ck(cudaMemset2D(devPtr, pitch, 0, sizeof(T) * cols, rows));
}
//拷贝构造函数
__host__ __device__ Patch(const Patch <h)
{
this->devPtr = lth.devPtr;
this->rows = lth.rows;
this->pitch = lth.pitch;
this->cols = lth.cols;
}
~Patch()
{
// cudaFree(devPtr);
}
void release()
{
cudaFree(devPtr);
}
__host__ void upload(const T *host_ptr_arg, size_t host_step_arg)
{
ck(cudaMemcpy2D(devPtr, pitch, host_ptr_arg, host_step_arg, cols * sizeof(T), rows, cudaMemcpyHostToDevice));
}
__host__ void download(const T *host_ptr_arg, size_t host_step_arg)
{
// if (host_step_arg == 0 || devPtr == nullptr || pitch == 0)
{
printf("%x,%d %x,%ld\n", host_ptr_arg, host_step_arg, devPtr, pitch);
}
ck(cudaMemcpy2D((void *)host_ptr_arg, host_step_arg, devPtr, pitch, sizeof(T) * cols, rows, cudaMemcpyDeviceToHost));
}
__device__ inline T &operator()(size_t rows, size_t cols)
{
// if (rows < pitch)
// return mat[x];
return *((devPtr + rows * pitch / sizeof(T) + cols));
}
__host__ void print()
{
printf("%ld %ld %ld\n", pitch, rows, cols);
}
};
TSDF类
tsdf class
修改后的主函数
int main()
{
DataSet<float> dt("/home/u20/dataset/paper/f3_long_office");
ck(cudaGetLastError());
cv::viz::Viz3d viz1("viz1"), viz2("viz2");
viz1.showWidget("Coordinate", cv::viz::WCoordinateSystem());
TSDF tsdf(make_float3(512, 512, 512), make_int2(640, 480));
tsdf.pintr = new Intr(make_float4(550, 550, 320, 240));
for (int i = 0; i < dt.pose.frames; i++)
{
cv::Mat rgb = cv::imread(dt.color_path[i]);
cv::Mat depth = cv::imread(dt.depth_path[i], cv::IMREAD_ANYDEPTH);
tsdf.addScan(depth, rgb);
std::shared_ptr<Mat> cpu_cloud2;
Mat cpu_color;
tsdf.exportCloud(cpu_cloud2, cpu_color);
viz1.showWidget("depthmode", cv::viz::WCloud(*cpu_cloud2, cpu_color));
Mat depth_color, cpu_cloud;
tsdf.depth2cam(depth, rgb, depth_color, cpu_color, cv::Affine3f::Identity());
cv::Affine3f viewpose = cv::Affine3f::Identity();
viz1.showWidget("depth", cv::viz::WCloud(depth_color, cpu_color), viewpose.translate(cv::Vec3f(4, 0, 0)));
// cv::imshow("rgb", rgb);
// cv::imshow("depth", depth);
// cv::waitKey(100);
viz1.spin();
}
}
最后效果如下
————————————————
版权声明:本文为CSDN博主「SkyTangLei」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/LiQuKanNaShiYu/article/details/125016578
三维重建KInectFusion 学习笔记相关推荐
- 基于MVS的三维重建算法学习笔记(二)— 立体视觉的几何基础总结
基于MVS的三维重建算法学习笔记(二)- 立体视觉的几何基础总结 声明 概述 1. 常见三维数据类型 2. 三维形状的几种表达形式 3. 三维空间刚体运动 4. 李群和李代数 5. 相机标定 6. 非 ...
- 基于MVS的三维重建算法学习笔记(一)— MVS三维重建概述与OpenMVS开源框架配置
基于MVS的三维重建算法学习笔记(一)- MVS三维重建概述与OpenMVS开源框架配置 声明 1. MVS(Multi-view stereo)概述 稀疏重建与稠密重建的区别 稀疏重建--SFM(S ...
- 基于MVS的三维重建算法学习笔记(五)— 立体匹配经典算法PatchMatch论文翻译及要点解读
基于MVS的三维重建算法学习笔记(五)- 立体匹配经典算法PatchMatch论文翻译及要点解读 声明 问题提出 问题建模 通过PatchMatch获取平面参数--Inference via Patc ...
- 基于MVS的三维重建算法学习笔记(四)— 立体匹配经典算法Semi-Global Matching(SGM)论文翻译及要点解读
基于MVS的三维重建算法学习笔记(四)- 立体匹配经典算法Semi-Global Matching(SGM)论文翻译及要点解读 声明 SGM概述 Cost Calculation(像素代价计算)--M ...
- 【相机标定与三维重建原理及实现】学习笔记1——相机模型数学推导详解
目录 前言 一.小孔成像模型 二.坐标系的变换 1.世界坐标系到相机坐标系的变换(刚体变换)[xw^→xc^\boldsymbol {\hat{x_{w}}}\rightarrow \boldsymb ...
- CV学习笔记-立体视觉(点云模型、Spin image、三维重建)
立体视觉 1. 立体视觉概述 概述: 立体视觉是一种计算机视觉技术,其目的是从两幅或两幅以上的图像中推理出图像中的每个像素点的深度信息. 原理: 在二维图像中,只有宽高两个维度的信息,而如何辨识远近的 ...
- 人体三维重建SMPL、SMPLX、SMPLifyX学习笔记
本文基本是针对代码运行和Blender插件的使用来记录,原理和论文请自行查阅. 原理 请参考下面的文章(也可以看论文): SMPL学习笔记 人体捕捉:<SMPL-X> SMPLify-x ...
- Programming Computer Vision with Python (学习笔记一)
转载自:http://segmentfault.com/a/1190000003941588 介绍 <Programming Computer Vision with Python>是一本 ...
- 图像坐标:我想和世界坐标谈谈(A) 【计算机视觉学习笔记--双目视觉几何框架系列】
玉米竭力用轻松具体的描述来讲述双目三维重建中的一些数学问题.希望这样的方式让大家以一个轻松的心态阅读玉米的<计算机视觉学习笔记>双目视觉数学架构系列博客.这个系列博客旨在捋顺一下已标定的双 ...
最新文章
- jfinal js 拦截_jfinal全局数据拦截器
- iOS架构-静态库.a之依赖第三方静态库.a的制作(8)
- 2015c语言成绩查询,2015年3月全国计算机二级C语言选择第1套
- DebugView调试C#程序 学习总结
- Linq to SQL 下篇
- hibernate 延迟加载的错误 failed to lazily initialize a collection of role
- 为什么Docker对初创企业有意义
- Tensorflow代码转pytorch代码 函数的转换
- awk正则匹配nginx日志【原创】
- Linux 服务器安全加固方案
- pmp 第六版 模拟卷2疑难问题
- 爬取mzi.com妹子图片网站(requests库)
- 无线传感器部署的连接性架构和协议选项
- 中国DNA测序在药物发现市场中的应用市场深度研究分析报告
- IDEA启动tomcat找不到应用程序(localhost:8080)
- 中专计算机专业execl教案,计算机专项目化教案(EXCEL教案
- IP网络主动测评系统
- 七零年代摄影师Robert Mapplethorpe
- 第二讲 HTML再识(一)
- 【PP那些事儿】特殊采购类40