hagino3000's blog

平成アーカイブス (更新停止)

OpenNIからDepth情報を取得してcvGrayScaleImageに渡す

libfreenectを使っていたアプリのドライバをOpenNIに変えてみた。しかしDepthのピクセル情報を直接取得するAPIが見つからなかったので次の泥臭いコードを書いた。もうちょっとスマートに書ければいいんだけどC++難しい……。


ヘッダ宣言部

    ofxOpenNIContext  recordContext;
    ofxDepthGenerator  recordDepth;

    unsigned char * depth_pixels;
    ofxCvGrayscaleImage grayImage;


Setup

  recordContext.setup();
  recordContext.setupUsingXMLFile();
  recordDepth.setup(&recordContext);
  recordContext.toggleMirror();

  XnMapOutputMode map_mode; 
  map_mode.nXRes = XN_VGA_X_RES; 
  map_mode.nYRes = XN_VGA_Y_RES;
  map_mode.nFPS = 30;

  depth_pixels = new unsigned char[map_mode.nXRes * map_mode.nYRes * 4];
  memset(depth_pixels, 0, map_mode.nXRes * map_mode.nYRes * 4 * sizeof(unsigned char));

  grayImage.allocate(640, 480);


Update

  recordContext.update();
  xn::DepthGenerator& dgen = recordDepth.getXnDepthGenerator();
  xn::DepthMetaData dmd;
  dgen.GetMetaData(dmd);
  const XnDepthPixel* depth = dmd.Data();
  float max_depth = dgen.GetDeviceMaxDepth();

  int pos = 0;
  for (XnUInt16 y = dmd.YOffset(); y < dmd.YRes() + dmd.YOffset(); y++) {
    for (XnUInt16 x = 0; x < dmd.XRes(); x++, depth++){
      depth_pixels[pos++] = (XnUInt16)(((*depth) / (max_depth / 256)));
    }
  }
  grayImage.setFromPixels(depth_pixels, 640, 480);

あとはOpenCVで好きな用に処理ができる。しかしメモリアクセスとかしたくないので、OpenNIのpythonバインディングを調べてみる価値はありそう。