/Kinect

Kinect 3D Video Capture Project

Primary LanguageC++GNU General Public License v2.0GPL-2.0

========================================================================
README for Kinect 3D Video Capture Project version 2.8
Copyright (c) 2010-2013 Oliver Kreylos
========================================================================

Requirements
============

This software requires the Vrui VR toolkit, version 3.1 build 001 or
newer. It also requires libusb version 1.0, and that Vrui was configured
with support for libusb prior to its installation. To properly work with
multiple Kinect-for-Xbox version 1473 and/or Kinect-for-Windows devices,
the libusb library needs to provide USB bus topology query functions
such as those provided by the libusbx fork. This software can optionally
create Kinect 3D video streaming plug-ins for Vrui's collaboration
infrastructure (version 2.6 or newer). The presence of Vrui's
collaboration infrastructure will be detected automatically during the
build process.

Installation Guide
==================

It is recommended to download or move the source packages for Vrui and
the Kinect 3D Video Capture Project into a src directory underneath the
user's home directory. Otherwise, references to ~/src in the following
instructions need to be changed.

0. Install Vrui from ~/src/Vrui-<version>-<build> (see Vrui README file).

0.5. (Optional) Install Vrui's collaboration infrastructure from
     ~/src/CollaborationInfrastructure-<version> (see its README file).

1. Change into ~/src directory and unpack the Kinect 3D Video Capture
   Project tarball:
   > cd ~/src
   > tar xfz <download path>/Kinect-<version>.tar.gz
   - or -
   > tar xf <download path>/Kinect-<version>.tar

2. Change into the Kinect 3D Video Capture Project's base directory:
   > cd Kinect-<version>

3. If the Vrui version installed in step 0 was not 3.1, or Vrui's
   installation directory was changed from the default of ~/Vrui-3.1,
   adapt the makefile using a text editor. Change the value of
   VRUI_MAKEDIR close to the beginning of the file as follows:
   VRUI_MAKEDIR := <Vrui install dir>/share/make
   Where <Vrui install dir> is the installation directory chosen in
   step 0. Use $(HOME) to refer to the user's home directory instead
   of ~.

4. Build the Kinect 3D Video Capture Project:
   > make

5. Install the Kinect 3D Video Capture Project:
   > make install

6. (Optional, Linux-only) Install a udev rule file to give access to all
   Kinect devices to all users, local and remote. Read below for details
   and security considerations.
   > make installudevrule
   This will ask for the user's password to copy the rule file,
   70-Kinect.rules, into the udev rule directory /etc/udev/rules.d.

Use
===

1. Run ./bin/KinectUtil list to list all Kinect devices connected to the
   host computer.

2a. Run ./bin/KinectUtil getCalib <camera index> to download factory
    calibration data from the <camera index>-th Kinect device on the
    host's USB bus (with the first device having index 0) and create a
    intrinsic camera calibration file for that device in the Kinect
    package's configuration file directory.

-- or --

2b. Run ./bin/RawKinectViewer <camera index> to intrinsically calibrate
    the <camera index>-th Kinect device on the host's USB bus (with the
    first device having index 0), using a semi-transparent checkerboard
    calibration target (see next section for details). This generates a
    binary IntrinsicParameters-<serial number>.dat file in
    <Vrui install dir>/etc/Kinect-<version>, where <serial number> is
    the unique factory-assigned serial number of the Kinect device as
    displayed in step 1.

Step 2 (a or b) only have to be performed once for each Kinect device,
unless the resulting calibration proves unsatisfactory. Kinect devices
typically retain their intrinsic calibration over time.

3. Run ./bin/KinectViewer -c <camera index>, where <camera index> is the
   zero-based index of the Kinect device to use if there are multiple
   ones.

Installing a udev rule (Linux-only)
===================================

By default, Kinect devices can only be accessed by the root user. This
is inconvenient and a security risk, as all Kinect applications must be
run as root. The Kinect package contains a udev rule file to give full
access to any Kinect device to any user, see optional installation step
6 above. After the rule file has been installed (and all Kinect devices
have been unplugged and re-plugged), regular users can work with the
devices.

Security concerns: At this time, the rule file gives access to all
connected Kinect devices to *all* users, whether logged in locally or
remotely, e.g., via ssh. This means that a remotely logged-in user could
turn on the camera or microphones to spy on a local user. Ideally,
access to the Kinect device would only be granted to the single user
currently owning the console. However, the way how this is done is
currently somewhat in flux, with the previous way of assigning ACL
control via udev rules being deprecated. Until a new method arises,
users can install the global-access udev rule at their own risks.

Intrinsically Calibrating a Single Kinect
=========================================

Before a Kinect can be used as a 3D camera, its two cameras need to be
calibrated. Calibration will calculate a 4x4 projection matrix to map
the depth camera's image stream into 3D space as a 3D point cloud or
triangulated surface, and a 4x4 projection matrix to map the color
camera's image stream onto that point cloud or surface. After proper
calibration, the virtual 3D objects captured by a Kinect will precisely
match the original real objects in shape and size.

Intrinsic calibration has two sub-procedures. The first, optional, one
is to calculate per-pixel depth correction equations. Due to radial lens
distortion in the IR pattern projector and the IR camera, a completely
flat surface seen by the Kinect will not be reconstructed as a flat
surface, but as a bowl shape. Depth correction will calculate a linear
equation for each depth pixel that can rectify distance values. The
second sub-procedure is to calculate 4x4 homogeneous depth unprojection
and color projection matrices. The results of sub-procedure two depend
on sub-procedure one, meaning that the second has to be performed every
time after the first one is performed.

Per-pixel Depth Correction
--------------------------

Calculating per-pixel depth correction equations only requires a flat
and ideally vertical surface large enough to fill the Kinect's
field-of-view at larger distances (up to about 2 meters). These are the
calibration procedure's steps:

1. Start RawKinectViewer for the Kinect to be calibrated.

2. Create a "Calibrate Depth Lens" tool by binding it to two (2) buttons
   (keyboard keys or mouse buttons). Here, we will use the keys "1" and
   "2". Pressing the "1" key will capture the current depth image as a
   calibration point, and pressing the "2" key will calculate per-pixel
   depth correction equations after several depth images have been
   captured.

3. Move the Kinect such that it faces the flat surface orthogonally and
   at close distance. The best approach is to position the Kinect to be
   roughly orthogonal to the surface, and push it so close that the
   entire depth image turns black (this happens at a distance of around
   50cm). Then slowly pull the Kinect back until about half the pixels
   have valid depth values. Then carefully rotate the Kinect until the
   valid pixels are distributed evenly across the depth image, and then
   pull back slightly further until most or all pixels have valid depth.

4. Press the "1" key to capture the current depth image. This will
   capture a number of frames, as indicated by the pop-up window. Do not
   move the Kinect while the pop-up window stays on the screen.

5. Move the Kinect further back, ideally until a sharp change in depth
   mapping color. Carefully rotate the Kinect such that pixels of
   different colors are evenly distributed, and adjust the distance
   until there are approximately the same number of pixels of either
   color.

6. Repeat from step 4, until the distance from the Kinect to the flat
   surface is larger than the largest distance you intend to capture
   during use, or repeat until the Kinect is approximately 2m away from
   the surface (the maximum practical capture distance).

7. Press the "2" key to calculate per-pixel depth correction equations.
   When the calculation is complete, the correction parameters will
   automatically be written to a DepthCorrection-<serial number>.dat
   file in the Kinect package's configuration directory.

8. Exit from RawKinectViewer.

Projection Matrix Calculation
-----------------------------

The new intrinsic calibration method uses a semi-transparent
checkerboard calibration target. The idea is that the target looks like
a checkerboard both to the depth and color cameras. The user presents
the calibration target to the Kinect in a sequence of different poses,
and manually matches a 2D distorted grid to the observed calibration
target in the depth and color cameras' views using the RawKinectViewer
utility. After a sufficient number of poses have been captured,
RawKinectViewer calculates the two calibration matrices and stores them
in a uniquely identified file for subsequent retrieval whenever a Kinect
device is activated.

The easiest and most precise way to build a semi-transparent
checkerboard is to print a grid pattern onto a large sheet of paper,
glue the entire sheet of paper onto an IR-transparent glass plate, cut
precisely along all grid lines using a sharp knife and metal ruler, and
then peel off every other paper square and remove any glue residue from
the now transparent tiles. The grid should have an odd number of tiles
in both directions such that all four corner tiles can stay opaque. Mark
the center of the lower-left corner tile with a small dot (big enough to
be visible in the Kinect's color image stream). This mark will be used
to check for grid alignment during calibration.

The number of tiles, and the size of each tile, can be configured in
RawKinectViewer, but the default grid layout has 7x5 tiles of 3.5"x3.5"
each. This leads to an overall target size of 24.5"x17.5", which is just
the right size to cover the Kinect's full viewing range.

The following is the intrinsic calibration procedure for a Kinect. There
are two tutorial videos on YouTube:
* http://www.youtube.com/watch?v=Qo05LVxdlfo explains steps 0 to 9 in
  the following procedure.
* http://www.youtube.com/watch?v=VQh4joyZwx8 explains step 10 in the
  following procedure.

These are the steps:

0. Prepare calibration target

1. Start RawKinectViewer for the Kinect to be calibrated. If the
   calibration target does not have the default layout, specify the
   layout using the -gridSize and -tileSize command line options.

2. Create a "Draw Grids" tool by binding it to five (5) buttons
   (keyboard keys or mouse buttons). Here, we will use the keys "1"
   through "5". This will create two green grids, one in the depth and
   one in the color image stream. The grid can be deformed by grabbing
   any grid intersection using the mouse and the "1" key, or translated
   by grabbing the dot in the center of the grid, or rotated around
   the center by grabbing the dot slightly outside the right edge of
   the grid, again using the "1" key.

3. Place the calibration target in front of the Kinect at the next
   position and orientation. The target should be placed in a range of
   distances, starting from the near depth cutoff to the end of the
   desired tracking range, and in a variety of orientations from
   straight-on to about 45 degree angles. Calibration requires at least
   4 calibration poses, but ideally a larger number to improve
   calibration quality.

4. Collect an average depth frame by turning on the "Average Frames"
   button in the main menu. Wait until the depth image does not change
   anymore.

5. Align both the depth and color grids grids to the observed grids. The
   dot in the center of the lower-left corner tile must roughly coincide
   with the mark in the lower-left corner tile of the calibration target
   to ensure that the grid is not flipped or rotated. The orientation of
   the depth and color stream grids will be very similar.

6. Store the current calibration grids by pressing the "2" key.

7. Turn off the "Average Frames" button in the main menu so that the
   depth image stream updates in real time again.

8. Repeat from step 3 with the next calibration pose.

9. After all calibration poses have been captured, calculate the
   intrinsic calibration by pressing the "4" key. This will print some
   diagnostic information to the terminal, and create the calibration
   file specific to the Kinect device in the Kinect package's
   configuration directory. The files are named
   IntrinsicParameters-<serial number>.dat and contain the two
   calibration matrices in binary format. They cannot be hand-edited.

10. After calibration, use KinectViewer and a 3D measurement tool to
    ensure that the size and shape of the virtual calibration target as
    reconstructed by the Kinect matches the real calibration target. A
    good calibration will create a match to a few percent. Keep in mind
    that measurements inside KinectViewer will be reported in
    centimeters.

There is a complementary write-up of the calibration procedure at
http://doc-ok.org/?p=289

Recording 3D Movies
===================

KinectViewer now has a built-in recorder for 3D movies from one or more
Kinect devices. When running a live view (using one or more
-c <Kinect index> and/or -p <server host> <server port> command line
arguments), the live 3D streams can be saved to a set of files by
selecting the "Save Streams" main menu entry. KinectViewer will ask for
a file name prefix, and then save the depth and color streams of all
enabled Kinect devices to files <prefix>-<index>.depth and
<prefix>-<index>.color. It will also record synchronized audio from the
default capture device (selectable from the sound control panel) and
save it to <prefix>.wav.

Previously recorded 3D movies can be played back by running KinectViewer
with one or more -f <file name prefix>-<index> arguments, one per saved
3D stream, and an optional -s <sound file name> argument to play back
synchronized audio.

Merging 3D Facades from Multiple Kinects
========================================

To merge the 3D reconstructions of multiple Kinect cameras, first
intrinsically calibrate each one using RawKinectViewer, as described
above and shown in the videos. Then extrinsically calibrate all Kinect
devices with respect to an arbitrarily chosen world coordinate system.

1. Place calibration target into field of view of all Kinect devices to
   be calibrated (use RawKinectViewer on each to check).

2. For each Kinect device:

   2a. Run RawKinectViewer and fit a grid to the calibration target's
       image in the depth stream (it is not necessary to fit to the
       color stream).

   2b. Save and unproject the grid to receive a list of 3D tie points on
       the console.

   2c. Copy the tie points into a file KinectPoints-<serial number>.csv.

3. Create a file TargetPoints.csv, containing the 3D interior corner
   positions of the calibration target, in some arbitrary right-handed
   world coordinate system using an arbitrary unit of measurement, in
   the same order as printed by RawKinectViewer (going from left to
   right, and then bottom to top). See example target file below.

4. For each Kinect device:

   4a. Run the Kinect device's tie points and the target points through
       AlignPoints:
       AlignPoints -OG KinectPoints-<serial number>.csv TargetPoints.csv

   4b. Observe the mismatches between purple camera points and green
       target points in AlignPoints' display. If the discrepancies are
       too large, or there is no fit at all, repeat step two for the
       Kinect device.

   4c. Paste the final best fitting transform displayed by AlignPoints
       (everything after the "Best transformation:" header) into a
       ExtrinsicParameters-<serial number>.txt file in the Kinect
       package's configuration directory (Kinect-<version> in the Vrui
       installation's etc directory).

5. Run KinectViewer on all Kinect devices. This will show all individual
   3D video streams matching more or less seamlessly, depending on how
   much care was taken during intrinsic and extrinsic calibration. Under
   ideal circumstances, there should be no noticeable mismatches between
   individual streams.

Unlike intrinsic calibration, extrinsic calibration has to be repeated
any time any of the calibrated Kinect devices are moved, even by very
little. It is recommended to rigidly attach all Kinect devices to a
sturdy frame before attempting precise extrinsic calibration in a
production setting. If precision is paramount, it might even be
necessary to repeat calibration periodically if nothing changed, to
account for time-varying deformations inside the devices themselves.

An example TargetPoints.csv file, for a 5x4 calibration grid with a tile
size of 3" (a 5x4 grid has 4x3 interior corners):

0, 0, 0
3, 0, 0
6, 0, 0
9, 0, 0
0, 3, 0
3, 3, 0
6, 3, 0
9, 3, 0
0, 6, 0
3, 6, 0
6, 6, 0
9, 6, 0

The resulting world space will use whatever units were used to define
the target points; in the example above, world space will use inches.

There is a complementary write-up of the calibration procedure at
http://doc-ok.org/?p=295