2014年10月1日水曜日

【kinect使ってみる。】座標のずれ

kinect記事前回では、depth画像とcolor画像の座標のズレを合わすところまで入てやりました。

↓これで座標を変換しているらしい
NuiImageGetColorPixelCoordinatesFromDepthPixelAtResolution()

しかし、それでも若干ずれている気がする~で終わりました。 

今回はそれをとりあえず直すことをやってみます。



※プログラミングスキルは初心者なので間違いや無駄等あると思います。


事前にに保存した画像でなんやかんややるので下記のプログラムではKinectは使っていません。


#include <iostream>
#include <opencv2\opencv.hpp>

using namespace std;
using namespace cv;

int main(int argc, char* argv[]){

 Mat depth, depth2; //depth2:ズラす用
 int counter = 0;
 char readBuf[256];
 char writeBuf[256];

 //動画で書き出す用
 //double fps = 15;
 //VideoWriter wDepth("wDepth.avi", CV_FOURCC('D', 'I', 'B', ' '), fps, cv::Size(640, 480), true);

 while (1){

  //事前に保存した画像の読み込み
  /*
  保存時にファイル名に連番を振っていたので
  counterで番号を回しながら読み込んで行きます。
  自分の場合、別のディレクトリに保存していました。
  */
  sprintf_s(readBuf, "..\\元画像保存ディレクトリ\\ファイル名%04d.jpg", counter);

  depth = imread(readBuf);
  depth2 = Mat::zeros(480, 640, CV_8UC3); //とりあえず真っ黒を用意
 if (depth.data == NULL) break;

  for (int y = 0; y < depth.rows; y++){

   Vec3b* ptrDepth = depth.ptr<Vec3b>(y);
   Vec3b* ptrDepth2 = depth2.ptr<Vec3b>(y); //ズラす用

   for (int x = 0; x < depth.cols; x++){

    if (x + 13 < depth2.cols)
     ptrDepth2[x + 13] = ptrDepth[x]; //ここで右に13ズラす

   }
  }


  //表示
  cv::imshow("depth", depth);
  cv::imshow("depth2", depth2);


  //静止画で書き出す
  sprintf_s(writeBuf, "保存先ディレクトリ\\保存ファイル名%04d.jpg", counter); 
  imwrite(writeBuf, depth2);

  //動画で書き出す
  //wDepth << depth2;

  //キー入力
  int key = cv::waitKey(10);
  if (key == 'q') break;


  counter++;
 }//while

 //終了
 //wDepth.release();
 cv::destroyAllWindows();
}








実行結果
元画像:



ずらした画像:





別途編集ソフト使って重ね合わせてみる
color画像:



color画像と元depth画像:




color画像とズラしたdepth画像:







画素にアクセスして x について右にズラしただけです。

ずらしたものを静止画で保存しています。

元の深度画像とカラー画像を合わせてみると横方向にずれているように見えます。

それを単純に右にずらしました。なんとなく合ってるよね?

(もし、元画像の方でdepthとcolorで取得のタイミングが異なる場合は時間とかでラベル付けしたり肉眼で比較してみて合わせてだいたい同じタイミングの画像を探してみるとか。)


きっともっとスマートな方法があるのだと思いますが、勉強不足ゆえこんな感じです。

肉眼を頼りにずれを調節しているので、正確さは保障できないと思います。とりあえずです。



今回は以上。


---[追記]-----

ある論文(出典見失った;・・・たしか阪大かどこかだったような)によると
Kinectはカラーカメラとデプスカメラは非同期らしいので、そもそもズレがあるようです。
ただ、フレームを取得する間隔はどちらも一定で、その幅がカラーとデプスでは異なるようなのでズレが生じているらしいです。

まぁだから↑のように単純に座標をズラしただけじゃダメってことだと思います。

ただXBOX版の時の話なので、今はどうなのか・・・。また調べてみようと思います。

--------


参考:
http://d.akiroom.com/2012-06/opencv-pixel-read-write-get-set/
http://kassymemo.blogspot.jp/2011/09/opencv2cvmat.html











0 件のコメント:

コメントを投稿