深度图像+彩色图像=彩色点云
一、保存到ply文件
要求:深度图像是16位,已知相机参数,需要"stdafx.h"这个头文件
结果:生成彩色点云并保存到ply文件
//功能:彩色图像+深度图像=彩色点云ply文件
//可以用哦,非常好哦
#include "stdafx.h"
// C++ 标准库
#include <iostream>
#include <string>
using namespace std;
// OpenCV 库
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
// PCL 库
#include <pcl/io/pcd_io.h>
#include <pcl/io/ply_io.h>
#include <pcl/point_types.h>
// 定义点云类型
typedef pcl::PointXYZRGBA PointT;
typedef pcl::PointCloud<PointT> PointCloud;
// 相机内参(这里参数借鉴的别人的,我改过好像没什么区别,有时间还是要自己检测一下自己相机的参数)????????????????
const double camera_factor = 1000;
const double camera_cx = 263.73696;
const double camera_cy = 201.72450;
const double camera_fx = 379.40726;
const double camera_fy = 378.54472;
// 主函数
int main(int argc, char** argv)
{
// 读取./data/rgb.png和./data/depth.png,并转化为点云
// 图像矩阵
cv::Mat rgb, depth;
// 使用cv::imread()来读取图像
// API: http://docs.opencv.org/modules/highgui/doc/reading_and_writing_images_and_video.html?highlight=imread#cv2.imread
rgb = cv::imread("2020- 5-14-13-36-21-rgb.png");
// rgb 图像是8UC3的彩色图像
// depth 是16UC1的单通道图像,注意flags设置-1,表示读取原始数据不做任何修改
depth = cv::imread("2020- 5-14-13-36-21-depth.png", -1);
// 点云变量
// 使用智能指针,创建一个空点云。这种指针用完会自动释放。
PointCloud::Ptr cloud(new PointCloud);
// 遍历深度图
for (int m = 0; m < depth.rows; m++)
for (int n = 0; n < depth.cols; n++)
{
// 获取深度图中(m,n)处的值
ushort d = depth.ptr<ushort>(m)[n];
// d 可能没有值,若如此,跳过此点
if (d == 0)
continue;
// d 存在值,则向点云增加一个点
PointT p;
// 计算这个点的空间坐标
p.z = double(d) / camera_factor;
p.x = (n - camera_cx) * p.z / camera_fx;
p.y = (m - camera_cy) * p.z / camera_fy;
// 从rgb图像中获取它的颜色
// rgb是三通道的BGR格式图,所以按下面的顺序获取颜色
p.b = rgb.ptr<uchar>(m)[n * 3];
p.g = rgb.ptr<uchar>(m)[n * 3 + 1];
p.r = rgb.ptr<uchar>(m)[n * 3 + 2];
// 把p加入到点云中
cloud->points.push_back(p);
}
// 设置并保存点云
cloud->height = 1;
cloud->width = cloud->points.size();
cout << "point cloud size = " << cloud->points.size() << endl;
cloud->is_dense = false;
pcl::io::savePLYFile("2020- 5-14-13-36-21.ply", *cloud);
// 清除数据并退出
cloud->points.clear();
cout << "Point cloud saved." << endl;
return 0;
}
二、保存成txt文件
要求:深度图像是16位,已知相机参数,需要"stdafx.h"这个头文件
结果:生成彩色点云并保存成txt文件
//功能:彩色图像+深度图像=彩色点云txt文件
// AxGeneratePointCloudDemo.cpp : 定义控制台应用程序的入口点。
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
// OpenCV 库
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
// 相机内参
const double camera_factor = 1000;
const double camera_cx = 325.5;
const double camera_cy = 253.5;
const double camera_fx = 518.0;
const double camera_fy = 519.0;
int _tmain(int argc, _TCHAR* argv[])
{
// 图像矩阵
cv::Mat rgb, depth;
// 使用cv::imread()来读取图像
rgb = cv::imread("2020- 5-14-13-36-21-rgb.png");
// rgb 图像是8UC3的彩色图像
// depth 是16UC1的单通道图像,注意flags设置-1,表示读取原始数据不做任何修改
depth = cv::imread("2020- 5-14-13-36-21-depth.png", -1);
std::string fileNameSave = "2020- 5-14-13-36-21.txt";
FILE *fileSave = fopen(fileNameSave.c_str(), "w");
if (fileSave == NULL)
{
return 0;
}
// 遍历深度图
for (int m = 0; m < depth.rows; m++)
for (int n = 0; n < depth.cols; n++)
{
// 获取深度图中(m,n)处的值
ushort d = depth.ptr<ushort>(m)[n];
// d 可能没有值,若如此,跳过此点
if (d == 0)
continue;
// d 存在值,则向点云增加一个点
float x, y, z;
int r, g, b;
// 计算这个点的空间坐标
z = double(d) / camera_factor;
x = (n - camera_cx) * z / camera_fx;
y = (m - camera_cy) * z / camera_fy;
// 从rgb图像中获取它的颜色
// rgb是三通道的BGR格式图,所以按下面的顺序获取颜色
b = rgb.ptr<uchar>(m)[n * 3];
g = rgb.ptr<uchar>(m)[n * 3 + 1];
r = rgb.ptr<uchar>(m)[n * 3 + 2];
fprintf(fileSave, "%f %f %f %d %d %d\n", x, y, z, r, g, b);
}
fclose(fileSave);
system("pause");
return 0;
}