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++的拼裝還得解決呀!(微笑)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/355426.html
標籤:其他
上一篇:python 如何安裝cv2庫
下一篇:DASH標準&ABR演算法介紹
