本博客主要参考网络上的教程博客,加上自己遇到的问题。
环境:win8_x64、VS2013、OpenCV2.4.9、PCL1.7.2、Kinect SDK2.0
主要参考博客:http://www.pclcn.org/bbs/forum.php?mod=viewthread&tid=1195
本博客用到的库和软件链接:http://pan.baidu.com/s/1dFw1PQD 密码:ob48
一、安装依赖库
a、安装OpenCV这里安装的是OpenCV2.4.9
推荐教程:http://blog.csdn.net/pinbodexiaozhu/article/details/39889995/
b、安装PCL这里安装的是PCL1.7.2
推荐教程:http://blog.csdn.net/caimagic/article/details/51395084
c、安装Kinect SDK2.0
直接安装,按提示操作即可。
官网SDK下载链接:https://www.microsoft.com/en-us/download/details.aspx?id=44561
安装完成后,在VS中新建空项目,
在属性管理器->C/C++->附加包含目录 添加C:\Program Files\Microsoft SDKs\Kinect\v2.0_1409\inc
在属性管理器->链接器->常规->附加库目录 添加C:\Program Files\Microsoft SDKs\Kinect\v2.0_1409\Lib\x86
在属性管理器->链接器->输入->附加依赖项 添加
Kinect20.VisualGestureBuilder.lib Kinect20.lib Kinect20.Face.lib Kinect20.Fusion.lib
在解决方案资源管理器中添加下面的源文件kinect2_grabber.cpp和kinect2_grabber.h后编译运行即可看到点云窗口。
二、代码
代码源文件在网盘Kinect_v2_点云获取文件夹中的kinect2_grabber.cpp和kinect2_grabber.h
源码网盘链接:http://pan.baidu.com/s/1jH4iZdG 密码:9jw8
另还有CMakeLists.txt供camake编译使用
CMakeLists.txt
cmake_minimum_required( VERSION 2.8 )
set( CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}" ${CMAKE_MODULE_PATH} )
project( sample )
add_executable( sample kinect2_grabber.h main.cpp )
set_property( DIRECTORY PROPERTY VS_STARTUP_PROJECT "sample" )
# Find Packages
find_package( PCL 1.7.2 REQUIRED )
find_package( KinectSDK2 REQUIRED )
if( PCL_FOUND AND KinectSDK2_FOUND )
# Additional Include Directories
include_directories( ${PCL_INCLUDE_DIRS} )
include_directories( ${KinectSDK2_INCLUDE_DIRS} )
# Preprocessor Definitions
add_definitions( ${PCL_DEFINITIONS} )
# Additional Library Directories
link_directories( ${PCL_LIBRARY_DIRS} )
link_directories( ${KinectSDK2_LIBRARY_DIRS} )
# Additional Dependencies
target_link_libraries( sample ${PCL_LIBRARIES} )
target_link_libraries( sample ${KinectSDK2_LIBRARIES} )
endif()
kinect2_grabber.cpp
// Disable Error C4996 that occur when using Boost.Signals2.
#ifdef _DEBUG
#define _SCL_SECURE_NO_WARNINGS
#endif
#include "kinect2_grabber.h"
#include
typedef pcl::PointXYZRGBA PointType;
int main( int argc, char* argv[] )
{
// PCL Visualizer
boost::shared_ptr viewer(
new pcl::visualization::PCLVisualizer( "Point Cloud Viewer" ) );
viewer->setCameraPosition( 0.0, 0.0, -2.5, 0.0, 0.0, 0.0 );
// Point Cloud
pcl::PointCloud::ConstPtr cloud;
// Retrieved Point Cloud Callback Function
boost::mutex mutex;
boost::function::ConstPtr& )> function =
[&cloud, &mutex]( const pcl::PointCloud::ConstPtr& ptr ){
boost::mutex::scoped_lock lock( mutex );
/* Point Cloud Processing */
cloud = ptr->makeShared();
};
// Kinect2Grabber
// boost::shared_ptr grabber = boost::make_shared();
boost::shared_ptr grabber = boost::shared_ptr(new pcl::Kinect2Grabber);
// Register Callback Function
boost::signals2::connection connection = grabber->registerCallback( function );
// Start Grabber
grabber->start();
while( !viewer->wasStopped() ){
// Update Viewer
viewer->spinOnce();
boost::mutex::scoped_try_lock lock( mutex );
if( lock.owns_lock() && cloud ){
// Update Point Cloud
if( !viewer->updatePointCloud( cloud, "cloud" ) ){
viewer->addPointCloud( cloud, "cloud" );
}
}
}
// Stop Grabber
grabber->stop();
// Disconnect Callback Function
if( connection.connected() ){
connection.disconnect();
}
return 0;
}
kinect2_grabber.h
// Kinect2Grabber is pcl::Grabber to retrieve the point cloud data from Kinect v2 using Kinect for Windows SDK 2.x.
// This source code is licensed under the MIT license. Please see the License in License.txt.
#ifndef KINECT2_GRABBER
#define KINECT2_GRABBER
#define NOMINMAX
#include
#include
#include
#include
#include
#include
namespace pcl
{
struct pcl::PointXYZ;
struct pcl::PointXYZI;
struct pcl::PointXYZRGB;
struct pcl::PointXYZRGBA;
template class pcl::PointCloud;
template
inline void SafeRelease( Interface *& IRelease )
{
if( IRelease != NULL ){
IRelease->Release();
IRelease = NULL;
}
}
class Kinect2Grabber : public pcl::Grabber
{
public:
Kinect2Grabber();
virtual ~Kinect2Grabber() throw ();
virtual void start();
virtual void stop();
virtual bool isRunning() const;
virtual std::string getName() const;
virtual float getFramesPerSecond() const;
typedef void ( signal_Kinect2_PointXYZ )( const boost::shared_ptr>& );
typedef void ( signal_Kinect2_PointXYZI )( const boost::shared_ptr>& );
typedef void ( signal_Kinect2_PointXYZRGB )( const boost::shared_ptr>& );
typedef void ( signal_Kinect2_PointXYZRGBA )( const boost::shared_ptr>& );
protected:
boost::signals2::signal* signal_PointXYZ;
boost::signals2::signal* signal_PointXYZI;
boost::signals2::signal* signal_PointXYZRGB;
boost::signals2::signal* signal_PointXYZRGBA;
pcl::PointCloud::Ptr convertDepthToPointXYZ( UINT16* depthBuffer );
pcl::PointCloud::Ptr convertInfraredDepthToPointXYZI( UINT16* infraredBuffer, UINT16* depthBuffer );
pcl::PointCloud::Ptr convertRGBDepthToPointXYZRGB( RGBQUAD* colorBuffer, UINT16* depthBuffer );
pcl::PointCloud::Ptr convertRGBADepthToPointXYZRGBA( RGBQUAD* colorBuffer, UINT16* depthBuffer );
boost::thread thread;
mutable boost::mutex mutex;
void threadFunction();
bool quit;
bool running;
HRESULT result;
IKinectSensor* sensor;
ICoordinateMapper* mapper;
IColorFrameSource* colorSource;
IColorFrameReader* colorReader;
IDepthFrameSource* depthSource;
IDepthFrameReader* depthReader;
IInfraredFrameSource* infraredSource;
IInfraredFrameReader* infraredReader;
int colorWidth;
int colorHeight;
std::vector colorBuffer;
int depthWidth;
int depthHeight;
std::vector depthBuffer;
int infraredWidth;
int infraredHeight;
std::vector infraredBuffer;
};
pcl::Kinect2Grabber::Kinect2Grabber()
: sensor( nullptr )
, mapper( nullptr )
, colorSource( nullptr )
, colorReader( nullptr )
, depthSource( nullptr )
, depthReader( nullptr )
, infraredSource( nullptr )
, infraredReader( nullptr )
, result( S_OK )
, colorWidth( 1920 )
, colorHeight( 1080 )
, colorBuffer()
, depthWidth( 512 )
, depthHeight( 424 )
, depthBuffer()
, infraredWidth( 512 )
, infraredHeight( 424 )
, infraredBuffer()
, running( false )
, quit( false )
, signal_PointXYZ( nullptr )
, signal_PointXYZI( nullptr )
, signal_PointXYZRGB( nullptr )
, signal_PointXYZRGBA( nullptr )
{
// Create Sensor Instance
result = GetDefaultKinectSensor( &sensor );
if( FAILED( result ) ){
throw std::exception( "Exception : GetDefaultKinectSensor()" );
}
// Open Sensor
result = sensor->Open();
if( FAILED( result ) ){
throw std::exception( "Exception : IKinectSensor::Open()" );
}
// Retrieved Coordinate Mapper
result = sensor->get_CoordinateMapper( &mapper );
if( FAILED( result ) ){
throw std::exception( "Exception : IKinectSensor::get_CoordinateMapper()" );
}
// Retrieved Color Frame Source
result = sensor->get_ColorFrameSource( &colorSource );
if( FAILED( result ) ){
throw std::exception( "Exception : IKinectSensor::get_ColorFrameSource()" );
}
// Retrieved Depth Frame Source
result = sensor->get_DepthFrameSource( &depthSource );
if( FAILED( result ) ){
throw std::exception( "Exception : IKinectSensor::get_DepthFrameSource()" );
}
// Retrieved Infrared Frame Source
result = sensor->get_InfraredFrameSource( &infraredSource );
if( FAILED( result ) ){
throw std::exception( "Exception : IKinectSensor::get_InfraredFrameSource()" );
}
// Retrieved Color Frame Size
IFrameDescription* colorDescription;
result = colorSource->get_FrameDescription( &colorDescription );
if( FAILED( result ) ){
throw std::exception( "Exception : IColorFrameSource::get_FrameDescription()" );
}
result = colorDescription->get_Width( &colorWidth ); // 1920
if( FAILED( result ) ){
throw std::exception( "Exception : IFrameDescription::get_Width()" );
}
result = colorDescription->get_Height( &colorHeight ); // 1080
if( FAILED( result ) ){
throw std::exception( "Exception : IFrameDescription::get_Height()" );
}
SafeRelease( colorDescription );
// To Reserve Color Frame Buffer
colorBuffer.resize( colorWidth * colorHeight );
// Retrieved Depth Frame Size
IFrameDescription* depthDescription;
result = depthSource->get_FrameDescription( &depthDescription );
if( FAILED( result ) ){
throw std::exception( "Exception : IDepthFrameSource::get_FrameDescription()" );
}
result = depthDescription->get_Width( &depthWidth ); // 512
if( FAILED( result ) ){
throw std::exception( "Exception : IFrameDescription::get_Width()" );
}
result = depthDescription->get_Height( &depthHeight ); // 424
if( FAILED( result ) ){
throw std::exception( "Exception : IFrameDescription::get_Height()" );
}
SafeRelease( depthDescription );
// To Reserve Depth Frame Buffer
depthBuffer.resize( depthWidth * depthHeight );
// Retrieved Infrared Frame Size
IFrameDescription* infraredDescription;
result = infraredSource->get_FrameDescription( &infraredDescription );
if( FAILED( result ) ){
throw std::exception( "Exception : IInfraredFrameSource::get_FrameDescription()" );
}
result = infraredDescription->get_Width( &infraredWidth ); // 512
if( FAILED( result ) ){
throw std::exception( "Exception : IFrameDescription::get_Width()" );
}
result = infraredDescription->get_Height( &infraredHeight ); // 424
if( FAILED( result ) ){
throw std::exception( "Exception : IFrameDescription::get_Height()" );
}
SafeRelease( infraredDescription );
// To Reserve Infrared Frame Buffer
infraredBuffer.resize( infraredWidth * infraredHeight );
signal_PointXYZ = createSignal();
signal_PointXYZI = createSignal();
signal_PointXYZRGB = createSignal();
signal_PointXYZRGBA = createSignal();
}
pcl::Kinect2Grabber::~Kinect2Grabber() throw()
{
stop();
disconnect_all_slots();
disconnect_all_slots();
disconnect_all_slots();
disconnect_all_slots();
thread.join();
// End Processing
if( sensor ){
sensor->Close();
}
SafeRelease( sensor );
SafeRelease( mapper );
SafeRelease( colorSource );
SafeRelease( colorReader );
SafeRelease( depthSource );
SafeRelease( depthReader );
SafeRelease( infraredSource );
SafeRelease( infraredReader );
}
void pcl::Kinect2Grabber::start()
{
// Open Color Frame Reader
result = colorSource->OpenReader( &colorReader );
if( FAILED( result ) ){
throw std::exception( "Exception : IColorFrameSource::OpenReader()" );
}
// Open Depth Frame Reader
result = depthSource->OpenReader( &depthReader );
if( FAILED( result ) ){
throw std::exception( "Exception : IDepthFrameSource::OpenReader()" );
}
// Open Infrared Frame Reader
result = infraredSource->OpenReader( &infraredReader );
if( FAILED( result ) ){
throw std::exception( "Exception : IInfraredFrameSource::OpenReader()" );
}
running = true;
thread = boost::thread( &Kinect2Grabber::threadFunction, this );
}
void pcl::Kinect2Grabber::stop()
{
boost::unique_lock lock( mutex );
quit = true;
running = false;
lock.unlock();
}
bool pcl::Kinect2Grabber::isRunning() const
{
boost::unique_lock lock( mutex );
return running;
lock.unlock();
}
std::string pcl::Kinect2Grabber::getName() const
{
return std::string( "Kinect2Grabber" );
}
float pcl::Kinect2Grabber::getFramesPerSecond() const
{
return 30.0f;
}
void pcl::Kinect2Grabber::threadFunction()
{
while( !quit ){
boost::unique_lock lock( mutex );
// Acquire Latest Color Frame
IColorFrame* colorFrame = nullptr;
result = colorReader->AcquireLatestFrame( &colorFrame );
if( SUCCEEDED( result ) ){
// Retrieved Color Data
result = colorFrame->CopyConvertedFrameDataToArray( colorBuffer.size() * sizeof( RGBQUAD ), reinterpret_cast( &colorBuffer[0] ), ColorImageFormat::ColorImageFormat_Bgra );
if( FAILED( result ) ){
throw std::exception( "Exception : IColorFrame::CopyConvertedFrameDataToArray()" );
}
}
SafeRelease( colorFrame );
// Acquire Latest Depth Frame
IDepthFrame* depthFrame = nullptr;
result = depthReader->AcquireLatestFrame( &depthFrame );
if( SUCCEEDED( result ) ){
// Retrieved Depth Data
result = depthFrame->CopyFrameDataToArray( depthBuffer.size(), &depthBuffer[0] );
if( FAILED( result ) ){
throw std::exception( "Exception : IDepthFrame::CopyFrameDataToArray()" );
}
}
SafeRelease( depthFrame );
// Acquire Latest Infrared Frame
IInfraredFrame* infraredFrame = nullptr;
result = infraredReader->AcquireLatestFrame( &infraredFrame );
if( SUCCEEDED( result ) ){
// Retrieved Infrared Data
result = infraredFrame->CopyFrameDataToArray( infraredBuffer.size(), &infraredBuffer[0] );
if( FAILED( result ) ){
throw std::exception( "Exception : IInfraredFrame::CopyFrameDataToArray()" );
}
}
SafeRelease( infraredFrame );
lock.unlock();
if( signal_PointXYZ->num_slots() > 0 ){
signal_PointXYZ->operator()( convertDepthToPointXYZ( &depthBuffer[0] ) );
}
if( signal_PointXYZI->num_slots() > 0 ){
signal_PointXYZI->operator()( convertInfraredDepthToPointXYZI( &infraredBuffer[0], &depthBuffer[0] ) );
}
if( signal_PointXYZRGB->num_slots() > 0 ){
signal_PointXYZRGB->operator()( convertRGBDepthToPointXYZRGB( &colorBuffer[0], &depthBuffer[0] ) );
}
if( signal_PointXYZRGBA->num_slots() > 0 ){
signal_PointXYZRGBA->operator()( convertRGBADepthToPointXYZRGBA( &colorBuffer[0], &depthBuffer[0] ) );
}
}
}
pcl::PointCloud::Ptr pcl::Kinect2Grabber::convertDepthToPointXYZ( UINT16* depthBuffer )
{
pcl::PointCloud::Ptr cloud( new pcl::PointCloud() );
cloud->width = static_cast( depthWidth );
cloud->height = static_cast( depthHeight );
cloud->is_dense = false;
cloud->points.resize( cloud->height * cloud->width );
pcl::PointXYZ* pt = &cloud->points[0];
for( int y = 0; y < depthHeight; y++ ){
for( int x = 0; x < depthWidth; x++, pt++ ){
pcl::PointXYZ point;
DepthSpacePoint depthSpacePoint = { static_cast( x ), static_cast( y ) };
UINT16 depth = depthBuffer[y * depthWidth + x];
// Coordinate Mapping Depth to Camera Space, and Setting PointCloud XYZ
CameraSpacePoint cameraSpacePoint = { 0.0f, 0.0f, 0.0f };
mapper->MapDepthPointToCameraSpace( depthSpacePoint, depth, &cameraSpacePoint );
point.x = cameraSpacePoint.X;
point.y = cameraSpacePoint.Y;
point.z = cameraSpacePoint.Z;
*pt = point;
}
}
return cloud;
}
pcl::PointCloud::Ptr pcl::Kinect2Grabber::convertInfraredDepthToPointXYZI( UINT16* infraredBuffer, UINT16* depthBuffer )
{
pcl::PointCloud::Ptr cloud( new pcl::PointCloud() );
cloud->width = static_cast( depthWidth );
cloud->height = static_cast( depthHeight );
cloud->is_dense = false;
cloud->points.resize( cloud->height * cloud->width );
pcl::PointXYZI* pt = &cloud->points[0];
for( int y = 0; y < depthHeight; y++ ){
for( int x = 0; x < depthWidth; x++, pt++ ){
pcl::PointXYZI point;
DepthSpacePoint depthSpacePoint = { static_cast( x ), static_cast( y ) };
UINT16 depth = depthBuffer[y * depthWidth + x];
// Setting PointCloud Intensity
point.intensity = static_cast( infraredBuffer[y * depthWidth + x] );
// Coordinate Mapping Depth to Camera Space, and Setting PointCloud XYZ
CameraSpacePoint cameraSpacePoint = { 0.0f, 0.0f, 0.0f };
mapper->MapDepthPointToCameraSpace( depthSpacePoint, depth, &cameraSpacePoint );
point.x = cameraSpacePoint.X;
point.y = cameraSpacePoint.Y;
point.z = cameraSpacePoint.Z;
*pt = point;
}
}
return cloud;
}
pcl::PointCloud::Ptr pcl::Kinect2Grabber::convertRGBDepthToPointXYZRGB( RGBQUAD* colorBuffer, UINT16* depthBuffer )
{
pcl::PointCloud::Ptr cloud( new pcl::PointCloud() );
cloud->width = static_cast( depthWidth );
cloud->height = static_cast( depthHeight );
cloud->is_dense = false;
cloud->points.resize( cloud->height * cloud->width );
pcl::PointXYZRGB* pt = &cloud->points[0];
for( int y = 0; y < depthHeight; y++ ){
for( int x = 0; x < depthWidth; x++, pt++ ){
pcl::PointXYZRGB point;
DepthSpacePoint depthSpacePoint = { static_cast( x ), static_cast( y ) };
UINT16 depth = depthBuffer[y * depthWidth + x];
// Coordinate Mapping Depth to Color Space, and Setting PointCloud RGB
ColorSpacePoint colorSpacePoint = { 0.0f, 0.0f };
mapper->MapDepthPointToColorSpace( depthSpacePoint, depth, &colorSpacePoint );
int colorX = static_cast( std::floor( colorSpacePoint.X + 0.5f ) );
int colorY = static_cast( std::floor( colorSpacePoint.Y + 0.5f ) );
if( ( 0 <= colorX ) && ( colorX < colorWidth ) && ( 0 <= colorY ) && ( colorY < colorHeight ) ){
RGBQUAD color = colorBuffer[colorY * colorWidth + colorX];
point.b = color.rgbBlue;
point.g = color.rgbGreen;
point.r = color.rgbRed;
}
// Coordinate Mapping Depth to Camera Space, and Setting PointCloud XYZ
CameraSpacePoint cameraSpacePoint = { 0.0f, 0.0f, 0.0f };
mapper->MapDepthPointToCameraSpace( depthSpacePoint, depth, &cameraSpacePoint );
if( ( 0 <= colorX ) && ( colorX < colorWidth ) && ( 0 <= colorY ) && ( colorY < colorHeight ) ){
point.x = cameraSpacePoint.X;
point.y = cameraSpacePoint.Y;
point.z = cameraSpacePoint.Z;
}
*pt = point;
}
}
return cloud;
}
pcl::PointCloud::Ptr pcl::Kinect2Grabber::convertRGBADepthToPointXYZRGBA( RGBQUAD* colorBuffer, UINT16* depthBuffer )
{
pcl::PointCloud::Ptr cloud( new pcl::PointCloud() );
cloud->width = static_cast( depthWidth );
cloud->height = static_cast( depthHeight );
cloud->is_dense = false;
cloud->points.resize( cloud->height * cloud->width );
pcl::PointXYZRGBA* pt = &cloud->points[0];
for( int y = 0; y < depthHeight; y++ ){
for( int x = 0; x < depthWidth; x++, pt++ ){
pcl::PointXYZRGBA point;
DepthSpacePoint depthSpacePoint = { static_cast( x ), static_cast( y ) };
UINT16 depth = depthBuffer[y * depthWidth + x];
// Coordinate Mapping Depth to Color Space, and Setting PointCloud RGBA
ColorSpacePoint colorSpacePoint = { 0.0f, 0.0f };
mapper->MapDepthPointToColorSpace( depthSpacePoint, depth, &colorSpacePoint );
int colorX = static_cast( std::floor( colorSpacePoint.X + 0.5f ) );
int colorY = static_cast( std::floor( colorSpacePoint.Y + 0.5f ) );
if( ( 0 <= colorX ) && ( colorX < colorWidth ) && ( 0 <= colorY ) && ( colorY < colorHeight ) ){
RGBQUAD color = colorBuffer[colorY * colorWidth + colorX];
point.b = color.rgbBlue;
point.g = color.rgbGreen;
point.r = color.rgbRed;
point.a = color.rgbReserved;
}
// Coordinate Mapping Depth to Camera Space, and Setting PointCloud XYZ
CameraSpacePoint cameraSpacePoint = { 0.0f, 0.0f, 0.0f };
mapper->MapDepthPointToCameraSpace( depthSpacePoint, depth, &cameraSpacePoint );
if( ( 0 <= colorX ) && ( colorX < colorWidth ) && ( 0 <= colorY ) && ( colorY < colorHeight ) ){
point.x = cameraSpacePoint.X;
point.y = cameraSpacePoint.Y;
point.z = cameraSpacePoint.Z;
}
*pt = point;
}
}
return cloud;
}
}
#endif KINECT2_GRABBER