ViSP  2.9.0
vpKinect.cpp
1 /****************************************************************************
2  *
3  * $Id: vpKinect.cpp 4574 2014-01-09 08:48:51Z fspindle $
4  *
5  *
6  * This file is part of the ViSP software.
7  * Copyright (C) 2005 - 2014 by INRIA. All rights reserved.
8  *
9  * This software is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * ("GPL") version 2 as published by the Free Software Foundation.
12  * See the file LICENSE.txt at the root directory of this source
13  * distribution for additional information about the GNU GPL.
14  *
15  * For using ViSP with software that can not be combined with the GNU
16  * GPL, please contact INRIA about acquiring a ViSP Professional
17  * Edition License.
18  *
19  * See http://www.irisa.fr/lagadic/visp/visp.html for more information.
20  *
21  * This software was developed at:
22  * INRIA Rennes - Bretagne Atlantique
23  * Campus Universitaire de Beaulieu
24  * 35042 Rennes Cedex
25  * France
26  * http://www.irisa.fr/lagadic
27  *
28  * If you have questions regarding the use of this file, please contact
29  * INRIA at visp@inria.fr
30  *
31  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
32  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
33  *
34  *
35  * Description:
36  * API for using a Microsoft Kinect device
37  * Requires libfreenect as a third party library
38  *
39  * Authors:
40  * Celine Teuliere
41  *
42  *****************************************************************************/
43 
44 #include <visp/vpConfig.h>
45 
46 // Note that libfreenect needs libusb-1.0 and libpthread
47 #if defined(VISP_HAVE_LIBFREENECT_AND_DEPENDENCIES)
48 
49 #include <limits> // numeric_limits
50 
51 #include <visp/vpKinect.h>
52 #include <visp/vpXmlParserCamera.h>
53 
57 vpKinect::vpKinect(freenect_context *ctx, int index)
58  : Freenect::FreenectDevice(ctx, index),
59  hd(240), wd(320),
60  m_new_rgb_frame(false),
61  m_new_depth_map(false),
62  m_new_depth_image(false),
63  height(480), width(640)
64 {
65  dmap.resize(height, width);
66  IRGB.resize(height, width);
67  vpPoseVector r(-0.0266,-0.0047,-0.0055,0.0320578,0.0169041,-0.0076519 );
68  rgbMir.buildFrom(r);
69  irMrgb = rgbMir.inverse();
70 }
71 
76 {
77 
78 }
79 
81 {
82  DMres = res;
83  height = 480;
84  width = 640;
86  if (DMres == DMAP_LOW_RES){
87  std::cout << "vpKinect::start LOW depth map resolution 240x320" << std::endl;
88  // IRcam.setparameters(IRcam.get_px()/2, IRcam.get_py()/2, IRcam.get_u0()/2, IRcam.get_v0()/2);
89  //IRcam.initPersProjWithoutDistortion(303.06,297.89,160.75,117.9);
90  IRcam.initPersProjWithDistortion(303.06, 297.89, 160.75, 117.9, -0.27, 0);
91  hd = 240;
92  wd = 320;
93  }
94  else
95  {
96  std::cout << "vpKinect::start MEDIUM depth map resolution 480x640" << std::endl;
97 
98  //IRcam.initPersProjWithoutDistortion(606.12,595.78,321.5,235.8);
99  IRcam.initPersProjWithDistortion(606.12, 595.78, 321.5, 235.8, -0.27, 0);
100  // Idmap.resize(height, width);
101  hd = 480;
102  wd = 640;
103  }
104 
105 #if defined(VISP_HAVE_ACCESS_TO_NAS) && defined(VISP_HAVE_XML2)
106  vpXmlParserCamera cameraParser;
107  char cameraXmlFile[FILENAME_MAX];
108  sprintf(cameraXmlFile, "/udd/fspindle/robot/Viper850/Viper850-code/include/const_camera_Viper850.xml");
109  cameraParser.parse(RGBcam, cameraXmlFile, "Generic-camera", vpCameraParameters::perspectiveProjWithDistortion, width, height);
110 #else
111 // RGBcam.initPersProjWithoutDistortion(525.53, 524.94, 309.9, 282.8);//old
112 // RGBcam.initPersProjWithDistortion(536.76, 537.25, 313.45, 273.27,0.04,-0.04);//old
113 // RGBcam.initPersProjWithoutDistortion(512.0559503505,511.9352058050,310.6693938678,267.0673901049);//new
114  RGBcam.initPersProjWithDistortion(522.5431816996,522.7191431808,311.4001982614,267.4283562142,0.0477365207,-0.0462326418);//new
115 #endif
116 
117  this->startVideo();
118  this->startDepth();
119 }
120 
122 {
123  this->stopVideo();
124  this->stopDepth();
125 }
126 
127 
131 void vpKinect::VideoCallback(void* rgb, uint32_t /* timestamp */)
132 {
133 // std::cout << "vpKinect Video callback" << std::endl;
134  vpMutex::vpScopedLock lock(m_rgb_mutex);
135  uint8_t* rgb_ = static_cast<uint8_t*>(rgb);
136  for (unsigned i = 0; i< height;i++){
137  for (unsigned j = 0 ; j < width ; j++)
138  {
139  IRGB[i][j].R = rgb_[3*(width*i +j)+0];
140  IRGB[i][j].G = rgb_[3*(width*i +j)+1];
141  IRGB[i][j].B = rgb_[3*(width*i +j)+2];
142  }
143  }
144 
145  m_new_rgb_frame = true;
146 }
147 
158 void vpKinect::DepthCallback(void* depth, uint32_t /* timestamp */)
159 {
160 // std::cout << "vpKinect Depth callback" << std::endl;
161  vpMutex::vpScopedLock lock(m_depth_mutex);
162  uint16_t* depth_ = static_cast<uint16_t*>(depth);
163  for (unsigned i = 0; i< height;i++){
164  for (unsigned j = 0 ; j < width ; j++)
165  {
166  dmap[i][j] = 0.1236f * tan(depth_[width*i +j] / 2842.5f + 1.1863f);//formula from http://openkinect.org/wiki/Imaging_Information
167  if(depth_[width*i +j]>1023){//Depth cannot be computed
168  dmap[i][j] = -1;
169  }
170  }
171  }
172  m_new_depth_map = true;
173  m_new_depth_image = true;
174 }
175 
176 
181 {
182  vpMutex::vpScopedLock lock(m_depth_mutex);
183  if (!m_new_depth_map)
184  return false;
185  map = this->dmap;
186  m_new_depth_map = false;
187  return true;
188 }
189 
190 
195 {
196  // vpMutex::vpScopedLock lock(m_depth_mutex);
197  vpImage<float> tempMap;
198  m_depth_mutex.lock();
199  if (!m_new_depth_map && !m_new_depth_image)
200  {
201  m_depth_mutex.unlock();
202  return false;
203  }
204  tempMap = dmap;
205 
206  m_new_depth_map = false;
207  m_new_depth_image = false;
208  m_depth_mutex.unlock();
209 
210  if ((Imap.getHeight()!=hd )||(map.getHeight()!=hd))
211  vpERROR_TRACE(1, "Image size does not match vpKinect DM resolution");
212  if (DMres == DMAP_LOW_RES){
213  for(unsigned int i = 0; i < hd; i++)
214  for(unsigned int j = 0; j < wd; j++){
215  map[i][j] = tempMap[i<<1][j<<1];
216  //if (map[i][j] != -1)
217  if (fabs(map[i][j] + 1.f) > std::numeric_limits<float>::epsilon())
218  Imap[i][j] = (unsigned char)(255*map[i][j]/5);
219  else
220  Imap[i][j] = 255;
221  }
222  }
223  else
224  {
225  for (unsigned i = 0; i< height;i++)
226  for (unsigned j = 0 ; j < width ; j++){
227  map[i][j] = tempMap[i][j];
228  //if (map[i][j] != -1)
229  if (fabs(map[i][j] + 1.f) > std::numeric_limits<float>::epsilon())
230  Imap[i][j] = (unsigned char)(255*map[i][j]/5);
231  else
232  Imap[i][j] = 255;
233  }
234  }
235 
236  return true;
237 }
238 
239 
244 {
245  vpMutex::vpScopedLock lock(m_rgb_mutex);
246  if (!m_new_rgb_frame)
247  return false;
248  IRGB = this->IRGB;
249  m_new_rgb_frame = false;
250  return true;
251 }
252 
256 void vpKinect::warpRGBFrame(const vpImage<vpRGBa> & Irgb, const vpImage<float> & Idepth, vpImage<vpRGBa> & IrgbWarped)
257 {
258  if ((Idepth.getHeight()!=hd )||(Idepth.getWidth()!=wd)){
259  vpERROR_TRACE(1, "Idepth image size does not match vpKinect DM resolution");
260  }
261  else{
262  if((IrgbWarped.getHeight()!=hd )||(IrgbWarped.getWidth()!=wd))
263  IrgbWarped.resize(hd, wd);
264  IrgbWarped=0;
265  double x1=0., y1=0., x2=0., y2=0., Z1, Z2;
266  vpImagePoint imgPoint(0,0);
267  double u=0., v=0.;
268  vpColVector P1(4),P2(4);
269 
270 // std::cout <<"rgbMir : "<<rgbMir<<std::endl;
271 
272  for (unsigned int i = 0; i< hd;i++)
273  for (unsigned int j = 0 ; j < wd ; j++){
275  vpPixelMeterConversion::convertPoint(IRcam, j, i, x1, y1);
276  Z1 = Idepth[i][j];
277  //if (Z1!=-1){
278  if (std::fabs(Z1+1) <= std::numeric_limits<double>::epsilon()){
279  P1[0]=x1*Z1;
280  P1[1]=y1*Z1;
281  P1[2]=Z1;
282  P1[3]=1;
283 
285  P2 = rgbMir*P1;
286  Z2 = P2[2];
287  //if (Z2!= 0){
288  if (std::fabs(Z2) > std::numeric_limits<double>::epsilon()){
289  x2 = P2[0]/P2[2];
290  y2 = P2[1]/P2[2];
291  }
292  else
293  std::cout<<"Z2 = 0 !!"<<std::endl;
294 
296  vpMeterPixelConversion::convertPoint(RGBcam, x2, y2, u, v);
297 
298  unsigned int u_ = (unsigned int)u;
299  unsigned int v_ = (unsigned int)v;
301  if ((u_<width)&&(v_<height)){
302  IrgbWarped[i][j] = Irgb[v_][u_];
303  }
304  else
305  IrgbWarped[i][j] = 0;
306  }
307  }
308  }
309 }
310 
311 
312 
313 
314 #endif // VISP_HAVE_LIBFREENECT
315 
Class that allows protection by mutex.
Definition: vpMutex.h:85
void start(vpKinect::vpDMResolution res=DMAP_LOW_RES)
Definition: vpKinect.cpp:80
vpDMResolution
Definition: vpKinect.h:118
void lock()
Definition: vpMutex.h:68
unsigned int getWidth() const
Definition: vpImage.h:159
#define vpERROR_TRACE
Definition: vpDebug.h:395
static void convertPoint(const vpCameraParameters &cam, const double &x, const double &y, double &u, double &v)
Point coordinates conversion from normalized coordinates in meter to pixel coordinates ...
void unlock()
Definition: vpMutex.h:71
static void convertPoint(const vpCameraParameters &cam, const double &u, const double &v, double &x, double &y)
Point coordinates conversion from pixel coordinates to normalized coordinates in meter...
XML parser to load and save intrinsic camera parameters.
void resize(const unsigned int h, const unsigned int w)
set the size of the image
Definition: vpImage.h:532
bool getRGB(vpImage< vpRGBa > &IRGB)
Definition: vpKinect.cpp:243
void warpRGBFrame(const vpImage< vpRGBa > &Irgb, const vpImage< float > &Idepth, vpImage< vpRGBa > &IrgbWarped)
Definition: vpKinect.cpp:256
Perspective projection with distortion model.
void buildFrom(const vpTranslationVector &t, const vpRotationMatrix &R)
Construction from translation vector and rotation matrix.
int parse(vpCameraParameters &cam, const char *filename, const std::string &camera_name, const vpCameraParameters::vpCameraParametersProjType &projModel, const unsigned int image_width=0, const unsigned int image_height=0)
Class that provides a data structure for the column vectors as well as a set of operations on these v...
Definition: vpColVector.h:72
The pose is a complete representation of every rigid motion in the euclidian space.
Definition: vpPoseVector.h:92
vpHomogeneousMatrix inverse() const
void stop()
Definition: vpKinect.cpp:121
unsigned int getHeight() const
Definition: vpImage.h:150
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:92
bool getDepthMap(vpImage< float > &map)
Definition: vpKinect.cpp:180
void initPersProjWithDistortion(const double px, const double py, const double u0, const double v0, const double kud, const double kdu)
virtual ~vpKinect()
Definition: vpKinect.cpp:75
vpKinect(freenect_context *ctx, int index)
Definition: vpKinect.cpp:57