ViSP  2.8.0
vpKinect.cpp
1 /****************************************************************************
2  *
3  * $Id: vpKinect.cpp 4329 2013-07-20 07:06:49Z fspindle $
4  *
5  *
6  * This file is part of the ViSP software.
7  * Copyright (C) 2005 - 2013 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:379
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
void resize(const unsigned int height, const unsigned int width)
set the size of the image
Definition: vpImage.h:535
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.
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