[Go to “teaching” in Morimoto Lab]

Game by ball 9

Here we study to use libraries of video and OpenCV.
この講義ではウェブカメラが必要です。


Lib > Video

Let’s see the example “GettingStartedCapture”.
Import Video library and select the below sample code.

[※mac OS Catalina以降の環境で、Videoライブラリのインポートエラーが起こる場合はこちらを参照。]

Let’s execute the above sample program.
The below is a result of printArray() by my pc.
They are from String[] camera = Capture.list();

Available cameras:
[0] “name=Rear Camera,size=640x480,fps=30”
[1] “name=Rear Camera,size=640x360,fps=30”
[2] “name=Rear Camera,size=3264x2448,fps=15”
[3] “name=Rear Camera,size=2592x1944,fps=15”
[4] “name=Rear Camera,size=1920x1080,fps=24”
[5] “name=Rear Camera,size=1600x1200,fps=30”
[6] “name=Rear Camera,size=1280x720,fps=60”
[7] “name=Front Camera,size=640x480,fps=30”
[8] “name=Front Camera,size=160x120,fps=30”
[9] “name=Front Camera,size=176x144,fps=30”
...

キャプチャーリストの番号は使うカメラを切り替えるために使います。
サンプルコードの下記の部分では、cameras[0]なので0番目のカメラを使っています。

cam = new Capture(this, cameras[0]);

Ex A: Capture a video by your PC using the above code. Then change the camera to use. And then, save frames using saveFrame(), and convert these frames to mov file.

saveFrame("frames2/line-######.png");

↑シャープ記号の数の桁の連番になります。
/で区切れば、それ以前の部分の名前のフォルダを自動で作成してくれます。
画像(フォルダを作成する場合はフォルダ)はプログラムのファイルと同じフォルダ内に作成されます。
画像ができたら、Processingのメニューのツールより、「ムービーメーカー」を選び、連番静止画のあるフォルダを選択して、「動画を作成」ボタンを押すと動画が作成されます。


Lib > OpenCV for Processing

OpenCV is a library of programming functions mainly aimed at real-time computer vision.
OpenCV is used for C, C++, C#, Java, … very popular!

Alt text

OpenCV for Processingで何ができるのでしょう?
以下の場所にあるサンプル名を見ると大体わかります。

サンプルの内、FaceDetectionをダブルクリックして実行しましょう
男性の顔の部分が四角で囲まれた画面が表示されると思います。
下記はそのサンプルコードに追記をしたものですが、
顔写真データがないと同じ挙動にならないので、
「サンプル」から実行し、
「名前を付けて保存」をして複製を作成して編集するとよいでしょう。

import gab.opencv.*; //openCVのライブラリ
import java.awt.Rectangle; //javaのRectangleクラス
OpenCV opencv; //OpenCVクラスの変数を定義
Rectangle[] faces;//1. Rectangleクラスの配列を定義(顔を複数検出できるため)
void setup() {
//静止画の読込
opencv = new OpenCV(this, "test.jpg");
size(1080, 720);
//2.
//顔のデータをロード→顔を検出
opencv.loadCascade(OpenCV.CASCADE_FRONTALFACE);
//目のデータをロード→目を検出
//opencv.loadCascade(OpenCV.CASCADE_EYE);
//口のデータをロード→口を検出
//opencv.loadCascade(OpenCV.CASCADE_MOUTH);
//顔を検出
faces = opencv.detect();
}
void draw() {
//入力画像の描画
image(opencv.getInput(), 0, 0);
noFill();
stroke(0, 255, 0);
strokeWeight(3);
//顔は複数検出可能なので、for文を使っているがここでは一つの顔のみ
for (int i = 0; i < faces.length; i++) {
rect(faces[i].x, faces[i].y, faces[i].width, faces[i].height);
}
}
  1. Rectangleクラスには、x, y, width, height (左上のx,y座標、横・縦幅)がある。詳細はこちら。

  2. setup内のloadCascadeのところに目や口を検出するコードを記載しています。
    このように、顔以外にも検出が可能ですので色々試してみましょう。
    更に他の部分を検出したい場合は、 こちらを参考にしてください。


Ex B. Let’s capture video by your PC and detect your face as shown below. And draw an image on your face (or eye or something) of the captured video in real-time.

自分のPCのカメラで撮った動画に対してリアルタイムに顔検出をするプログラムを書いてください(下にある動画のように)。
更に、何かしらの画像を読込み、キャプチャした動画の顔や目などの上に表示するようにしてください。

Alt text


Let’s see another example, OpticalFlow of OpenCV.

Optical flowは2つの画像間で各点がどう動いたのかを表します。
動画なら、一つ前のフレームのある位置が次のフレームでどこに行ったのかをベクトルで表します。
以下はOpenCV for ProcessingのOptical Flowの実行結果です。

Alt text
まずこのサンプルを実行しましょう。
OpenCV for processingのサンプルからOpticalFlowを開いて下さい。

下記のプログラムは少しサンプルに改変を加えています。

import gab.opencv.*;
import processing.video.*;
OpenCV opencv;
Movie video;
void setup() {
size(1136, 320);
video = new Movie(this, "sample1.mov");
opencv = new OpenCV(this, 568, 320);
video.loop();
video.play();
}
void draw() {
background(0);
if (video.width>0) {
//if (video.available()){
video.read();
opencv.loadImage(video);
opencv.calculateOpticalFlow();
image(video, 0, 0);
translate(video.width, 0);
stroke(255, 0, 0);
opencv.drawOpticalFlow();
PVector aveFlow = opencv.getAverageFlow();
int flowScale = 50;
stroke(255);
strokeWeight(2);
line(video.width/2, video.height/2, video.width/2 + aveFlow.x * flowScale, video.height / 2 + aveFlow.y * flowScale);
}
}
  1. available()はビデオの新しいフレームが読込可能になっているかどうかをboolean (true or false)で返しています。
    ※ifの中が式になっていない場合、中身がtrueなら{}内の処理をします。
    ここがうまくいかない場合もあり、代わりにvideo.widthが0より大きくなっているかどうかに置き換えるとうまくいくことがあります。

  2. getAverageFlow()は画面全体のoptical flowの平均を求める関数です。

Ex C. Edit the example to use captured video in real-time. And please use other methods of optical flow such as the below.

上記のサンプルコードを変更し、リアルタイムにカメラで取得した画像を入力としてください。
また、以下のような、optical flowを扱う他の関数を試してみてください

  1. getAverageFlowInRegion(x,y,width,height)
    It gets an average flow in the specified region.

  2. getFlowAt(x,y)
    It gets a flow at the specified position.

Ex D. Combine the optical flow with a ball. Add force to move a ball by the optical flow.

ボールにoptical flowで取得したベクトルで力を与えてください。

Hint: To interact with a ball, use getFlowInRegion() around the ball position.

2人以上で楽しむインタラクティブなアプリケーションなど実装してみてもよいと思います。

余裕のある人へ. サンプルプログラムBackgroundSubstractionを見てみよう。アレンジしてみよう。

背景差分法といって、背景と現在のカメラで取得した画像の差分をとることで、動いている部分を取り出す方法があります。
sampleにはこの使用例があります。
たとえば、人のシルエットを使った処理とか、これを使ってもいいと思います。
Footfalls 2006 | Tmema (Golan Levin & Zachary Lieberman)

Golan Levin and Collaborators Projects
Messa di Voceなどがおすすめ。


Reference

  1. If you would successfully implement this, if would be like this video. It is not very reactive.

  2. This is also good examples with the optical flow!

  3. OpticalFlow meets FlipFluids

コメント:
OpticalFlowはよく特定した物体の追従などに使われることが多いです。
それ以外の応用としては、ボールや流体など、何かに影響を与えるものが多いかなと思います。
他に軌跡を楽しむものもありますね。
アトラクターなどと組み合わせるときれいそう。


おまけ:p5.jsでもっとface tracking

講義で使っているProcessingはJavaベースのものですが、js (javascript)ベースのp5.jsというものもあります。
それぞれで、使えるライブラリなどが異なります。
clmtrackrはjs用のもので、顔の輪郭や感情認識などが手軽に行えます。
また、p5.jsはいくつか開発環境が考えられますが、webエディターもあります。
webエディターで公開されているclmtrackrを使ったプログラムを更に自分で編集して、色々な表現に使うこともできますね。
javaベースのものと変数の定義の仕方など少し違いますが、共通する部分も多いので、習得も難しくないかもしれません。

参考:
p5.js入門ページ
画像処理ウェブで動くサンプル