深度图像+rgb转化点云数据、点云数据打开、显示以及保存

  • 头文件
#include<iostream>
#include <fstream>
#include <stdio.h>
#include <string.h>
#include<pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/point_types.h>
  • 点云的打开
// 创建点云(指针)
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>); 
// 读入PCD格式的文件,如果文件不存在,返回-1
if (pcl::io::loadPCDFile<pcl::PointXYZ>("cloud.pcd", *cloud) == -1) {
		system("pause");
		return (-1);
}
std::cout << "Loaded "<< cloud->width * cloud->height	//总点数
	<< " data points from test_file.pcd with the following fields."<< std::endl;
//试显示前5个的点
for (size_t i = 0; i < 5; ++i){
	std::cerr << " " << cloud->points[i].x
			<< " " << cloud->points[i].y
			<< " " << cloud->points[i].z << std::endl;
}
  • 点云的保存
pcl::io::savePCDFile("cloud.pcd", *cloud);
  • 点云显示
pcl::visualization::CloudViewer viewer("pcd_before viewer");//显示点云
viewer.showCloud(cloud);
system("pause");//暂停显示防止闪退
  • 生成随机点云数据
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud1(new pcl::PointCloud<pcl::PointXYZ>);
	cloud1->width = 500;
	cloud1->height = 1;
	cloud1->points.resize(cloud1->width*cloud1->height);
	std::cout << "创建原始点云数据" << std::endl;
	for (size_t i = 0; i < cloud1->points.size(); ++i)
	{
		cloud1->points[i].x = 1024 * rand() / (RAND_MAX + 1.0f);
		cloud1->points[i].y = 1024 * rand() / (RAND_MAX + 1.0f);
		cloud1->points[i].z = 1024 * rand() / (RAND_MAX + 1.0f);
	}
	for (size_t i = 0; i < cloud1->points.size(); i++)
	{
		std::cerr << " " << cloud1->points[i].x << " "
			<< cloud1->points[i].y << " "
			<< cloud1->points[i].z << std::endl;
	}
	std::cout << "原始点云数据点数:" << cloud1->points.size() << std::endl ;
	pcl::io::savePCDFile("cloud.pcd", *cloud1);
  • 深度图像和rgb生成点云数据
#include <iostream>
#include <pcl/io/io.h>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <opencv2/opencv.hpp>
#include <string>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <pcl/visualization/cloud_viewer.h>
using namespace std;
// 定义点云类型

typedef pcl::PointXYZRGBA PointT;
typedef pcl::PointCloud<PointT> PointCloud;

// 相机内参
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 main(int argc, char** argv)
{
	// 读取rgb.png和depth.png到图像矩阵里
	cv::Mat rgb, depth;
	// 使用cv::imread()来读取图像
	rgb = cv::imread("color.png");
	cout << "read rgb" << endl;
	// rgb 图像是8UC3的彩色图像
	// depth 是16UC1的单通道图像,注意flags设置-1,表示读取原始数据不做任何修改
	depth = cv::imread("depth.png");
	cout << "read depth" << endl;

	// 使用智能指针,创建一个空点云。这种指针用完会自动释放。
	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);
			cout << cloud->points.size() << endl;
		}

	// 设置并保存点云
	cloud->height = 1;
	cloud->width = cloud->points.size();
	cout << "point cloud size = " << cloud->points.size() << endl;
	cloud->is_dense = false;
	try {
		pcl::io::savePCDFile("pcd.pcd", *cloud);
	}
	//异常处理
	catch (pcl::IOException &e) {
		cout << e.what() << endl;
	}

	//显示点云图
	pcl::visualization::CloudViewer view("Simple Cloud Viewer");//直接创造一个显示窗口
	view.showCloud(cloud);//再这个窗口显示点云

	pcl::io::savePCDFileASCII("projectpointcloud.pcd", *cloud);
	// 清除数据并退出
	cloud->points.clear();
	cout << "Point cloud saved." << endl;
	return 0;
}

原博文:https://blog.csdn.net/blademan1234/article/details/79796901

#include <pcl/io/openni_grabber.h>
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/filters/passthrough.h>
#include <pcl/io/pcd_io.h>
#include <pcl/common/transforms.h>
#include <string>
#include <iostream>
#include <vector>

boost::mutex cloud_mutex;
pcl::PointCloud<pcl::PointXYZ>::ConstPtr cloud_global;

class SimpleOpenNIViewer
{
public:
	SimpleOpenNIViewer() {}

	//回调函数,回传收到的点云到run()函数里
	void cloud_cb_(const pcl::PointCloud<pcl::PointXYZ>::ConstPtr &cloud, pcl::PointCloud<pcl::PointXYZ>::Ptr &cloud_out, bool* new_cloud_available_flag)
	{
		//锁住,不允许此段时间内,点云数据被修改
		cloud_mutex.lock();
		*cloud_out = *cloud;
		*new_cloud_available_flag = true;
		cloud_mutex.unlock();
	}

	//kinect读到的点云是在viewer.showCloud里是颠倒的,现在把它再颠倒过来
	    pcl::PointCloud<pcl::PointXYZ>::Ptr upsideDown(const pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_in) {
		pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_transformed(new pcl::PointCloud<pcl::PointXYZ>);
		Eigen::Matrix4f transform = Eigen::Matrix4f::Identity();
		transform(1, 1) = -1;
		transform(2, 2) = -1;
		pcl::transformPointCloud(*cloud_in, *cloud_transformed, transform);
		return cloud_transformed;
	}
	//突出中间的部分的点云
	pcl::PointCloud<pcl::PointXYZI>::Ptr highlightMiddleArea(const pcl::PointCloud<pcl::PointXYZ>::Ptr &cloud_in){
		pcl::PointCloud<pcl::PointXYZI>::Ptr cloud_out(new pcl::PointCloud<pcl::PointXYZI>);
		pcl::PassThrough<pcl::PointXYZ> pt;
		pcl::IndicesPtr reserve_indices(new std::vector <int>);

		pcl::copyPointCloud(*cloud_in, *cloud_out);
		pt.setInputCloud(cloud_in);
		pt.setFilterFieldName("x");
		//突出x方向上(-0.3,0.3)这个范围内的点云
		pt.setFilterLimits(-0.3, 0.3);
		pt.filter(*reserve_indices);
		for (int i = 0; i < (*reserve_indices).size(); i++) {
			cloud_out->points[(*reserve_indices)[i]].intensity = 10;
		}
		return cloud_out;
	}
	//代码的核心部分,整个流程都在这里安排
	void run(boost::shared_ptr<pcl::visualization::CloudViewer> viewer)
	{
		bool new_cloud_available_flag = false;
		pcl::Grabber* inter = new pcl::OpenNIGrabber();
		pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_out(new pcl::PointCloud<pcl::PointXYZ>);
		pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_tmp(new pcl::PointCloud<pcl::PointXYZ>);
		pcl::PointCloud<pcl::PointXYZI>::Ptr cloud_toshow(new pcl::PointCloud<pcl::PointXYZI>);

		//注册回调函数
		boost::function<void(const pcl::PointCloud<pcl::PointXYZ>::ConstPtr&)> f =
			boost::bind(&SimpleOpenNIViewer::cloud_cb_, this, _1, cloud_out, &new_cloud_available_flag);
		inter->registerCallback(f);
		//start()之后,点云数据源源不断的传到cloud_out
		inter->start();
		while (!viewer->wasStopped())
		{
			if (new_cloud_available_flag) {//如果有新的点云获取
				cloud_mutex.lock();       //锁住,不允许此段时间内,点云数据被修改
				cloud_tmp = upsideDown(cloud_out);//颠倒点云,为了可视化
				cloud_mutex.unlock();
				cloud_toshow = highlightMiddleArea(cloud_tmp);
				viewer->showCloud(cloud_toshow);//可视化点云
				cloud_global = cloud_tmp;       //传点云到keyboardEventOccured()里
				new_cloud_available_flag = false;
			}
		}
		inter->stop();
	}
};
//回调函数,当键盘有输入时,被调用
void keyboardEventOccured(const pcl::visualization::KeyboardEvent &event, void *nothing) {
	if (event.getKeySym() == "space" && event.keyDown()) {//当按下空格键时
		cout << "Space is pressed => pointcloud saved as output.pcd" << endl;
		pcl::io::savePCDFile("output.pcd", *cloud_global);
	}
}
int main()
{
	boost::shared_ptr<pcl::visualization::CloudViewer> viewer2(new pcl::visualization::CloudViewer("a viewer"));
	//绑定可视化窗口和键盘事件的函数
	viewer2->registerKeyboardCallback(keyboardEventOccured, (void*)NULL);

	SimpleOpenNIViewer v;
	v.run(viewer2);
	return 0;
}

原博文:https://blog.csdn.net/AmbitiousRuralDog/article/details/80375480


版权声明:本文为weixin_43214609原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。