1. 程式人生 > >利用opencv以及pcl將2D深度圖影象轉換為3D點雲

利用opencv以及pcl將2D深度圖影象轉換為3D點雲

#include <QtCore/QCoreApplication>
#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/point_types.h>

// 定義點雲型別
typedef pcl::PointXYZRGBA PointT;
typedef pcl::PointCloud<PointT> PointCloud;

// 相機內參
const double camera_factor = 700;
const double camera_cx = 256;
const double camera_cy = 212;
const double camera_fx = 363.0;
const double camera_fy = 363;
int main(int argc, char *argv[])
{
	QCoreApplication a(argc, argv);
	// 讀取./data/rgb.png和./data/depth.png,並轉化為點雲

	// 影象矩陣
	cv::Mat rgb, depth;
	// 使用cv::imread()來讀取影象
	
	rgb = cv::imread("F:/depth.png");
	// rgb 影象是8UC3的彩色影象
	// depth 是16UC1的單通道影象,注意flags設定-1,表示讀取原始資料不做任何修改
	depth = cv::imread("F:/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::savePCDFile("F:/222.pcd", *cloud);
	// 清除資料並退出
	cloud->points.clear();
	cout << "Point cloud saved." << endl;
	return a.exec();
}