- 头文件
#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版权协议,转载请附上原文出处链接和本声明。