LeapMotion v2.1に更新したofxLeapMotionでCamera Imagesの表示
(メモ)
LeapMotionの生画像取得APIがv2.1~公開されたそうなので、テストしてみます。
Dev向けSDKのV2.1のincludeとlibをofxLeapMotionの既存の物と置き換える。
PIなどの定数定義で引っかかるので、#ifndef~#endifで囲む。
ofxLeapMotion.h
//Raw Images
void setPolicyFlags();
void getRawImages();
void getDistorionImages();
ofImage surface[2];
ofImage distortion[2];
ofxLeapMotion.cpp
//Raw Images
void ofxLeapMotion::setPolicyFlags(){
Controller::PolicyFlag addImagePolicy = (Controller::PolicyFlag)(Controller::PolicyFlag::POLICY_IMAGES | ourController->policyFlags());
ourController->setPolicyFlags(addImagePolicy);
}
void ofxLeapMotion::getRawImages()
{
//Uses Cinder OpenGL wrapper
Leap::Frame frame = ourController->frame();ImageList images = frame.images();
for(int i = 0; i < 2; i++){
Image image = images[i];const unsigned char* image_buffer = image.data();
//Draw the raw image data as a greyscale bitmap
int cursor = 0;
for(int h=0; h<image.height(); h++){
for(int w=0; w<image.width(); w++){
surface[i].setColor(w,h,ofColor_<unsigned char>(image_buffer[cursor]));
cursor++;
}
}
surface[i].reloadTexture();
//surface[i].saveImage(string("raw") + to_string(i) + string(".jpg"));//Surface surface(image.width(), image.height(), image.width() * 4, SurfaceChannelOrder::RGBA);
//int cursor = 0;
//Surface::Iter iter = surface.getIter();
//while( iter.line() ) {
// while( iter.pixel() ) {
// iter.r() = image_buffer[cursor];
// iter.g() = iter.b() = iter.r();
// iter.a() = 255;
// cursor++;
// }
//}
}
}
testApp.cpp
update関数の中
leap.getRawImages();
//IMPORTANT! - tell ofxLeapMotion that the frame is no longer new.
leap.markFrameAsOld();
draw()関数の中
ofEnableLighting();
l1.enable();
l2.enable();leap.surface[0].draw(-400,100, 320, 240);
leap.surface[1].draw(80,100, 320, 240);
m1.begin();
m1.setShininess(0.6);
同様に、サンプルをちょっといじってofImageに合わせて、
void ofxLeapMotion::getRectifiedImages()
{
//Uses Cinder OpenGL wrapper
Leap::Frame frame = ourController->frame();//Draw the undistorted image using the warp() function
int targetWidth = 400;
int targetHeight = 400;//Iterate over target image pixels, converting xy to ray slope
unsigned char brightness[4] = {0,0,0,255}; //An array to hold the rgba color componentsfor(int i=0; i<2; i++){
ImageList images = frame.images();
for(int h=0; h<targetHeight; h++){
for(int w=0; w<targetWidth; w++){
//Normalize from pixel xy to range [0..1]
Vector input = Vector( (float)w/targetWidth, (float)h/targetHeight, 0);//Convert from normalized [0..1] to slope [-4..4]
input.x = (input.x - images[i].rayOffsetX()) / images[i].rayScaleX();
input.y = (input.y - images[i].rayOffsetY()) / images[i].rayScaleY();Vector pixel = images[i].warp(input);
if(pixel.x >= 0 && pixel.x < images[i].width() && pixel.y >= 0 && pixel.y < images[i].height()) {
int data_index = floor(pixel.y) * images[i].width() + floor(pixel.x); //xy to buffer index
brightness[0] = images[i].data()[data_index]; //Look up brightness value
brightness[2] = brightness[1] = brightness[0]; //Greyscale
} else {
brightness[0] = 255; //Display invalid pixels as red
brightness[2] = brightness[1] = 0;
}
distortion[i].setColor(w,h,ofColor(brightness[0], brightness[1], brightness[2]));
}
}
distortion[i].reloadTexture();
//distortion[i].saveImage(string("distortion") + to_string(i) + string(".jpg"));
}}
処理速度はとっても遅いので、cv::remap風に処理するか、GPUのexampleを参考に書き直した方が実用的です。
速さは多少マシバージョン。
std::vector<std::vector<int> > rectified_map;
を.hに追加。
void ofxLeapMotion::getRectifiedImages()
{
//Uses Cinder OpenGL wrapper
Leap::Frame frame = ourController->frame();//Draw the undistorted image using the warp() function
static const int targetWidth = 400;
static const int targetHeight = 400;static bool init_map = false;
ImageList images = frame.images();
if(!init_map){if(images[0].width() != 0){
rectified_map.resize(2);
for(int i=0; i<2; i++){
rectified_map[i].resize(targetWidth*targetHeight);
for(int h=0; h<targetHeight; h++){
for(int w=0; w<targetWidth; w++){
//Normalize from pixel xy to range [0..1]
Vector input = Vector( (float)w/targetWidth, (float)h/targetHeight, 0);//Convert from normalized [0..1] to slope [-4..4]
input.x = (input.x - images[i].rayOffsetX()) / images[i].rayScaleX();
input.y = (input.y - images[i].rayOffsetY()) / images[i].rayScaleY();Vector pixel = images[i].warp(input);
if(pixel.x >= 0 && pixel.x < images[i].width() && pixel.y >= 0 && pixel.y < images[i].height()) {
int data_index = floor(pixel.y) * images[i].width() + floor(pixel.x); //xy to buffer index
rectified_map[i][h*targetWidth+w] = data_index; //Look up brightness value
} else {
rectified_map[i][h*targetWidth+w] = -1;
}
}
}
}
init_map = true;}
else return;
}//Iterate over target image pixels, converting xy to ray slope
unsigned char brightness[4] = {0,0,0,255}; //An array to hold the rgba color componentsfor(int i=0; i<2; i++){
ImageList images = frame.images();
for(int h=0; h<targetHeight; h++){
for(int w=0; w<targetWidth; w++){
if(rectified_map[i][h*targetWidth+w]>=0){
brightness[0] = images[i].data()[rectified_map[i][h*targetWidth+w]]; //Look up brightness value
brightness[2] = brightness[1] = brightness[0]; //Greyscale
}
else{
brightness[0] = 255; //Display invalid pixels as red
brightness[2] = brightness[1] = 0;
}
distortion[i].setColor(w,h,ofColor(brightness[0], brightness[1], brightness[2]));
}
}
distortion[i].reloadTexture();
}}
[1] Camera Images — Leap Motion C++ SDK v2.1.0 Beta documentation