1. 程式人生 > >彩色圖和深度圖轉點雲

彩色圖和深度圖轉點雲

環境:windows10、VS2013、opencv 2.49、openNi、PCL1.8opencv 環境搭建參考PCL1.8+openNi搭建參考將上面的opencv和pcl的配置儲存到屬性表中,以便下一次快速引用。新建專案,選擇解決方案配置選擇Debug x64,屬性管理器的Debug|x64中新增上面兩個屬性表RGBDtoPC.cpp


#include "stdafx.h"

#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)
{
	// 讀取./data/rgb.png和./data/depth.png,並轉化為點雲

	// 影象矩陣
	cv::Mat rgb, depth;
	// 使用cv::imread()來讀取影象
	// API: http://docs.opencv.org/modules/highgui/doc/reading_and_writing_images_and_video.html?highlight=imread#cv2.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("E:\\Visual Studio2013\\project\\RGBDtoPC\\data\\pcd.pcd", *cloud);
		

	}
	catch (pcl::IOException &e){
		cout << e.what()<< endl;
	}
	//顯示點雲圖
	pcl::visualization::CloudViewer viewer("Simple Cloud Viewer");//直接創造一個顯示視窗
	viewer.showCloud(cloud);//再這個視窗顯示點雲
	while (!viewer.wasStopped())
	{
	}

	//pcl::io::savePCDFileASCII("E:\\Visual Studio2013\\projectpointcloud.pcd", *cloud);
	// 清除資料並退出
	cloud->points.clear();
	cout << "Point cloud saved." << endl;
	return 0;
}
執行後可能直接返回,提示pcl::io Exception單步執行發現cv::imread()並沒有讀取到圖片。原因如下opencv有cvLoadImage()和cv::imread()讀圖片的方法而後者的連結庫版本不正確:(debug下對應的庫為xxxd.lib,release的為xxx.lib)
連結器中的附加依賴項中同時新增帶d和不帶d的依賴項會出問題,如果用Debug除錯則只新增後面帶d的即可,將不帶d的刪除。我添加了這些opencv_calib3d249d.lib
opencv_contrib249d.lib
opencv_core249d.lib
opencv_features2d249d.lib
opencv_flann249d.lib
opencv_gpu249d.lib
opencv_highgui249d.lib
opencv_imgproc249d.lib
opencv_legacy249d.lib
opencv_ml249d.lib
opencv_nonfree249d.lib
opencv_objdetect249d.lib
opencv_photo249d.lib
opencv_stitching249d.lib
opencv_ts249d.lib
opencv_video249d.lib
opencv_videostab249d.lib顯示點雲圖參考:
//顯示點雲圖
	pcl::visualization::CloudViewer viewer("Simple Cloud Viewer");//直接創造一個顯示視窗
	viewer.showCloud(cloud);//再這個視窗顯示點雲
color.pngdepth.png執行結果深度圖和彩色圖沒有對準,可能的原因是在程式碼的相機內參設定不匹配。