???? 1. 点云环境
1.1点云 点云与三维图像的关系:三维图像是一种特殊的信息表达形式,其特征是表达的空间中三个维度的数据,表现形式包括:深度图(以灰度表达物体与相机的距离),几何模型(由CAD软件建立),点云模型(所有逆向工程设备都将物体采样成点云)。和二维图像相比,三维图像借助第三个维度的信息,可以实现天然的物体——背景解耦。点云数据是最为常见也是最基础的三维模型。点云模型往往由测量直接得到,每个点对应一个测量点,未经过其他处理手段,故包含了最大的信息量。这些信息隐藏在点云中需要以其他提取手段将其萃取出来,提取点云中信息的过程则为三维图像处理。 点云的概念:点云是在同一空间参考系下表达目标空间分布和目标表面特性的海量点集合,在获取物体表面每个采样点的空间坐标后,得到的是点的集合,称之为“点云”(Point Cloud)。
1.2环境配置
1.2.1PCL库安装 第一次:失败,解决不了,遂放弃重装系统。
第二次:
????????step1:安装ubuntu,出现grub-install致命错误,两天未解决,遂放弃,换u盘成功。
??????? step2:安装依赖库
sudo apt-get update
sudo apt-get install git build-essential linux-libc-dev
sudo apt-get install cmake cmake-gui
sudo apt-get install libusb-1.0-0-dev libusb-dev libudev-dev
sudo apt-get install mpi-default-dev openmpi-bin openmpi-common
sudo apt-get install libflann1.9 libflann-dev #和ubuntu18对应1.9
sudo apt-get install libeigen3-dev
sudo apt-get install libboost-all-dev
sudo apt-get install libvtk7.1-qt libvtk7.1 libvtk7-dev #新版7.1
sudo apt-get install libqhull* libgtest-dev
sudo apt-get install freeglut3-dev pkg-config
sudo apt-get install libxmu-dev libxi-dev
sudo apt-get install openjdk-8-jdk openjdk-8-jre #qt-sdk已被舍弃,改用此代码
??????? step3:下载
git clone https://github.com/PointCloudLibrary/pcl.git
??????? step4:编译
cd pcl
mkdir release
cd release
cmake -DCMAKE_BUILD_TYPE=None -DCMAKE_INSTALL_PREFIX=/usr \ -DBUILD_GPU=ON-DBUILD_apps=ON -DBUILD_examples=ON \ -DCMAKE_INSTALL_PREFIX=/usr ..
make
#编译完成后
sudo make install
??????? step5:检查
??????? 创建test_pcl文件夹,通过vscode创建test_pcl.cpp并写入
#include <iostream>
#include <pcl/common/common_headers.h>
#include <pcl/io/pcd_io.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/console/parse.h>
using namespace std;
int main(int argc, char **argv) {//柱型点云测试
cout << "Test PCL !" << endl;
pcl::PointCloud<pcl::PointXYZRGB>::Ptr point_cloud_ptr (new pcl::PointCloud<pcl::PointXYZRGB>);
uint8_t r(255), g(15), b(15);
for (float z(-1.0); z <= 1.0; z += 0.05) {//制作柱型点云集
for (float angle(0.0); angle <= 360.0; angle += 5.0) {
pcl::PointXYZRGB point;
point.x = cos (pcl::deg2rad(angle));
point.y = sin (pcl::deg2rad(angle));
point.z = z;
uint32_t rgb = (static_cast<uint32_t>(r) << 16 | static_cast<uint32_t>(g) << 8 | static_cast<uint32_t>(b));
point.rgb = *reinterpret_cast<float*>(&rgb);
point_cloud_ptr->points.push_back (point);
}
if (z < 0.0) {//颜色渐变
r -= 12;
g += 12;
}
else {
g -= 12;
b += 12;
}
}
point_cloud_ptr->width = (int) point_cloud_ptr->points.size ();
point_cloud_ptr->height = 1;
pcl::visualization::CloudViewer viewer ("pcl—test测试");
viewer.showCloud(point_cloud_ptr);
while (!viewer.wasStopped()){ };
return 0;
}
? ????????利用touch CMakeLists.txt,并写入
cmake_minimum_required(VERSION 2.6)
project(test_pcl)
find_package(PCL 1.2 REQUIRED)
include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})
add_executable(test_pcl test_pcl.cpp)
target_link_libraries (test_pcl ${PCL_LIBRARIES})
install(TARGETS test_pcl RUNTIME DESTINATION bin)
????????然后再在test_pcl文件夹下建一个build文件夹。 ????????开始编译: ??????? 在build文件夹中打开终端(在文件夹下右键+T) ??????? 终端输入
cmake ..
make
./test_pcl
出现
?除了文件名有乱码,基本完成!
1.2.2 安装realsense D455
??????? 注意从官网上安装适配本机内核的版本,否则显示无法连接。
????????下载解压
cd librealsense
sudo apt-get install libudev-dev pkg-config libgtk-3-dev
sudo apt-get install libusb-1.0-0-dev pkg-config
sudo apt-get install libglfw3-dev
sudo apt-get install libssl-dev
mkdir build
cd build
cmake ../ -DBUILD_EXAMPLES=true
make -j4
sudo make install
验证
realsense-viewer
1.2.3 安装openGL
????????参见Linux 下安装 OpenGL_csp123258的专栏-CSDN博客_linux安装opengl
1.2.4 安装glfw
????????参见Ubuntu下glfw的安装与使用_dxmcu的专栏-CSDN博客buntu下glfw的安装与使用_dxmcu的Ubuntu下glfw的安装与使用_dxmcu的专栏-CSDN博客
????????清华源,中科大源,和不换源都找不到glfw的依赖build-dep glfw的源代码包,跳过直接编译,不知道行不行。
1.2.5 安装opencv4.5.3
??????? 参见Ubuntu18安装opencv3.4_zhongqli的博客-CSDN博客 ??????
????????其中可能会出现?? errorE: unable to locate libjasper-dev
在终端输入 ????
sudo add-apt-repository "deb http://security.ubuntu.com/ubuntu xenial-security main"
sudo apt update
sudo apt upgrade
sudo apt install libjasper1 libjasper-dev
再来一次就能解决。
2. 法向量的求取 2.1法向量 基于局部表面拟合的方法首先由 Hoppe 等在基于有向距离函数(Signed Distance Function)的表面重建算法中提出假设点云的采样平面是处处光滑的,因此,任何点的局部邻域都可以用平面进行很好的拟合;为此,对于点云中的每个点p,获取与其最相近的k个相邻点,然后为这些点计算一个最小二乘意义上的局部平面 P,并找到法向量。
?
?
?2.2 PCL处理realsense的点云数据
初始想法:利用realsense获取的点云数据包括两种:照片数据.ply,录制数据.bag,但是pcl要处理的是pcd数据,因此要将.ply转成.pcd(x,y,z,RGB)格式,再导入到pcl中处理。
思路错误:不应该从realsense中把数据直接存下来,而是把数据读下来,直接用PCL处理返回法向量。
先从realsense中获取位置和颜色数据
#ifndef RSDEVICE_H
#define RSDEVICE_H
#include <librealsense/rs.hpp>
#include <QString>
#封装对realsense的操作
class rsdevice
{
public:
rs::context ctx;
rs::device * dev;
int devCount;
QString devName;
QString devSerial;
QString devFwVersion;
QString devCamType;
QString devIspFwVersion;
bool streamEnable;
public:
QString getDevName(){
return devName;
}
QString getDevSerial(){
return devSerial;
}
QString getDevFwVersion(){
return devFwVersion;
}
QString getCamType(){
return devCamType;
}
QString getIspFwVersion(){
return devIspFwVersion;
}
public:
rsdevice();
~rsdevice();
void initRsDevice();
void enableStream();
uchar * getFrameData();
bool isSteamEnable();
float getDistance(int x,int y);
};
#endif // RSDEVICE_H
#初始化摄像头
void rsdevice::initRsDevice()
{
devCount = ctx.get_device_count();
dev = ctx.get_device(0);
.....................
.....................
}
#开启摄像头数据流,在这里我们只开启两路数据,一路RGB彩色数据,一路深度摄像头数据
void rsdevice::enableStream(){
streamEnable = true;
dev->enable_stream(rs::stream::color, 640, 480, rs::format::rgb8, 60);
dev->enable_stream(rs::stream::depth,640,480, rs::format::z16, 60);
dev->start();
}
#获取RGBC彩色数据
uchar * rsdevice::getFrameData(){
dev->wait_for_frames();
return (uchar *) dev->get_frame_data(rs::stream::color);
}
#获取深度数据
float rsdevice::getDistance(int x, int y){
uint16_t *depthImage = (uint16_t *) dev->get_frame_data(rs::stream::depth);
float scale = dev->get_depth_scale();
rs::intrinsics depthIntrin = dev->get_stream_intrinsics(rs::stream::depth);
uint16_t depthValue = depthImage[y * depthIntrin.width + x];
float depthInMeters = depthValue * scale;
return depthInMeters;
}
再用PCL获取法向量
#PCL获取法向量
#include <pcl/point_types.h>
#include <pcl/features/normal_3d.h>
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
... read, pass in or create a point cloud ...
// Create the normal estimation class, and pass the input dataset to it
pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
ne.setInputCloud (cloud);
// Create an empty kdtree representation, and pass it to the normal estimation object.
// Its content will be filled inside the object, based on the given input dataset (as no other search surface is given).
pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ> ());
ne.setSearchMethod (tree);
// Output datasets
pcl::PointCloud<pcl::Normal>::Ptr cloud_normals (new pcl::PointCloud<pcl::Normal>);
// Use all neighbors in a sphere of radius 3cm
ne.setRadiusSearch (0.03);
// Compute the features
ne.compute (*cloud_normals);
// cloud_normals->points.size () should have the same size as the input cloud->points.size ()*
}
理论结束了,c++的拼装还得解决呀!(微笑)
|