「ComputerVision」カテゴリーアーカイブ

OpticalFlow220424

ProcessingのOpticalFlowで人の行動を測定しようという企画。過去に何回か話題にあがっている。これとかこれとか、これも。すごい前から「使えそう」と言ってる割に、一回も使っていない。今回は大島さんとの共同研究で、実際に利用することになりそうだ。

 ProcessingのOpenCVライブラリには、OpticalFlow関連のサンプルプログラムがある。基本的にOpticalFlowを視覚化するプログラムなのだが、こちらのサイトから、640×480の各点のデータを取得する方法を学び、右半分と左半分を別に平均し、グラフ化、さらにディスクに保存するプログラムを作成した。
 結果はまぁまぁ予想どおり。各点の移動方向はVectorで取得できる。さらにそれをmag()関数で大きさを求め、指定範囲の平均を求めている。ProcessingのPVectorの説明はここにある。測定範囲を視覚化し、さらにある程度GUIで指定できるようになると、実用性が増すようにも思えるが、現場の状況を見ないとなんとも言えないので、次のMTGで話あいましょう。

import gab.opencv.*;
import processing.video.*;

Capture video; // ライブカメラ
OpenCV opencv; // OpenCV

String savefile = "data/movement.csv";
PrintWriter output;

void setup() {

  size(640, 480); //画面サイズ
  video = new Capture(this, 640, 480);  //キャプチャーするカメラのサイズ
  opencv = new OpenCV(this, 640, 480);  //OpenCVの画面サイズ
  video.start();  //キャプチャー開始
  
  output = createWriter(savefile);  //出力用ファイル
}

/////////////////////////////////
void draw() {
  
  scale(1.0);  //描画スケール設定
  
  opencv.loadImage(video);  //カメラの画像をOpenCVに読み込み
  image(video, 0, 0 );      //カメラ画像を表示
  opencv.calculateOpticalFlow();  //OpticalFlowを計算
  stroke(255,0,0);            //描画設定
  opencv.drawOpticalFlow();    //OpticalFlowを描画


  float LFlow = averagedFlow(0,0,320,480).mag();
  float RFlow = averagedFlow(320,0,320,480).mag();
  print(abs(LFlow)+"/"+abs(RFlow)+"\n");
  output.println(abs(LFlow)+","+abs(RFlow));
  
  
  stroke(0,0,255);  
  rect(0,480-LFlow*100,10,480);
  rect(630,480-RFlow*100,640,480);
  
  //PVector aveFlow = opencv.getAverageFlow();
  //print(aveFlow.x+"/"+aveFlow.y+"\n");
}

//キャプチャーイベント
void captureEvent(Capture c) {
  c.read();
}


/////平均化されたFlowを取得
PVector averagedFlow(int x,int y,int w, int h){

  float xsum=0,ysum=0,xavg=0, yavg=0;
  float c=0;
  for(int i=x;i<x+w;i++){  
    for(int j=y;j<y+h;j++){
      PVector vec = opencv.getFlowAt(i,j);
      xsum+=(float)vec.x;
      ysum+=(float)vec.y;
      c=c+1;
    }
  }
  xavg=xsum/c;
  yavg=ysum/c;
  
  PVector rv=new PVector(0,0);
  rv.x=xavg;
  rv.y=yavg;
  
  return(rv);  //ベクトルで返す
}

//終了時処理
void dispose(){
  output.close();
  println( "dispose start");
}

void keyPressed() {
  if (key == TAB) {          // Tabキーに反応
    output.close();
    exit();
  }
}