-
Notifications
You must be signed in to change notification settings - Fork 1
/
KLCloud.cpp
171 lines (146 loc) · 5.27 KB
/
KLCloud.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
#include "KAPI.h"
#ifdef max
#undef max
#endif
#ifdef min
#undef min
#endif
#include <string>
#include "KLCloud.h"
using namespace std;
using namespace cv;
//------------------------------------------------------
//-------------- Pre-define Values ---------------------
//------------------------------------------------------
#define CLOUD_MAX_DEPTH 2.0f
#define CLOUD_NAME "Kinect Cloud"
#define CLOUD_POINT_RADIUS 0.01f
#define CLOUD_LINE_STICKNESS 0.5f
//------------------------------------------------------
//----------- Initialize Static Variables --------------
//------------------------------------------------------
const float KLCloud::badFloat = std::numeric_limits<float>::quiet_NaN();
//------------------------------------------------------
//----------- Constructor & Destructor -----------------
//------------------------------------------------------
KLCloud::KLCloud(BYTE** ppColor, BYTE** ppDepth, LONG** ppCoordinates, int width, int height):
m_pViewer(new pcl::visualization::PCLVisualizer("KL Viewer")),
m_pCloud(new pcl::PointCloud<PointType>)
{
m_ppColorBuffer = ppColor;
m_ppDepthBuffer = ppDepth;
m_ppColorCoordinates = ppCoordinates;
m_maxZ = CLOUD_MAX_DEPTH;
if(!m_ppColorBuffer||!m_ppDepthBuffer||!m_ppColorCoordinates)
exit(-1);
m_width = width;
m_height= height;
// Initialize point cloud
m_pCloud->width = width*height;
m_pCloud->height = 1;
m_pCloud->is_dense = false;
m_pCloud->points.resize(width*height);
// Initialize viewer
m_pViewer->setBackgroundColor(0,0,0);
pcl::visualization::PointCloudColorHandlerRGBField<PointType> rgb(m_pCloud);
m_pViewer->addPointCloud<PointType>(m_pCloud, rgb, CLOUD_NAME);
m_pViewer->setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, CLOUD_NAME);
m_pViewer->initCameraParameters();
}
KLCloud::~KLCloud(){
m_pViewer->removeAllPointClouds();
m_pCloud->clear();
}
//------------------------------------------------------
//--------------- Draw Point CLoud ---------------------
//------------------------------------------------------
bool KLCloud::clearPrevDrawing(){
PointType badPoint(0,0,0);
badPoint.x = badPoint.y = badPoint.z = badFloat;
m_pCloud->points.assign(m_pCloud->points.size(), badPoint);
m_pViewer->removeAllShapes();
return true;
}
bool KLCloud::drawKCLoud(){
int pointIndex = 0, depthDataIndex = 0;
USHORT* depthBuffer = (USHORT*) (*m_ppDepthBuffer);
for(DWORD y=0; y<m_height; y++){
for(DWORD x=0; x<m_width; x++){
// Process depth
PointType& point = m_pCloud->points[pointIndex];
Vector4 vec;
// Transform 2D point into 3D
vec = NuiTransformDepthImageToSkeleton(x,y,depthBuffer[depthDataIndex],NUI_IMAGE_RESOLUTION_640x480);
if(vec.z<m_maxZ&&vec.z>0.4f){
point.x = -vec.x;
point.y = vec.y;
point.z = vec.z;
// Process color
LONG colorX = (*m_ppColorCoordinates)[depthDataIndex*2];
LONG colorY = (*m_ppColorCoordinates)[depthDataIndex*2 + 1];
if(colorX>=0&&colorX<m_width&&colorY>=0&&colorY<m_height){
LONG colorIndex = colorX + colorY*m_width;
LONG colorValue = ((LONG*)(*m_ppColorBuffer))[colorIndex];
point.r = (colorValue & 0x00ff0000UL)>>16;
point.g = (colorValue & 0x0000ff00UL)>>8;
point.b = (colorValue & 0x000000ffUL);
}
}
pointIndex++;
depthDataIndex++;
}
}
return true;
}
static string strIdProducer(const string& prefixStr, int number){
string result(prefixStr);
result+="_";
result+=to_string(static_cast<long long>(number));
return result;
}
static string strIdProducer(const string& prefixStr, int number1, int number2){
string result(prefixStr);
result+="_";
result+=to_string(static_cast<long long>(number1));
result+="_";
result+=to_string(static_cast<long long>(number2));
return result;
}
bool KLCloud::drawLHand(const vector<Vec3d>& palms, const vector<vector<Vec3d>>& fingers){
// Check if palms number matches hands number
int handCount = (int)palms.size();
if(fingers.size()!=handCount){
cerr<<"Palms size conflicts with fingers size. "<<endl;
return false;
}
for(int i=0; i<handCount; i++){
PointType palmPoint;
palmPoint.x = -palms[i][0];
palmPoint.y = palms[i][1];
palmPoint.z = palms[i][2];
m_pViewer->addSphere(palmPoint, CLOUD_POINT_RADIUS, 0.0, 0.0, 1.0, strIdProducer("Palm", i));
int fingerCount = 0;
for(vector<Vec3d>::const_iterator it=fingers[i].cbegin(); it!=fingers[i].cend(); it++){
PointType fingerPoint;
fingerPoint.x = -(*it)[0];
fingerPoint.y = (*it)[1];
fingerPoint.z = (*it)[2];
m_pViewer->addSphere(fingerPoint, CLOUD_POINT_RADIUS, 0.0, 0.0, 1.0, strIdProducer("FingerTips",i, fingerCount));
m_pViewer->addLine(palmPoint, fingerPoint, 0.0, 0.0, 0.5, strIdProducer("Finger", i, fingerCount++));
}
}
return true;
}
bool KLCloud::updatePointCloud(const std::vector<cv::Vec3d>& palms, const std::vector<std::vector<cv::Vec3d>>& fingers){
if(m_pViewer->wasStopped())
return false;
if(!clearPrevDrawing())
return false;
if(!drawKCLoud())
return false;
if(!drawLHand(palms, fingers))
return false;
m_pViewer->updatePointCloud(m_pCloud, CLOUD_NAME);
m_pViewer->spinOnce();
return true;
}