みなさん,こんにちは
おかしょです.
学会で発表するときは,数値シミュレーションの結果を見せることもありますが,実験結果がある場合は実験のデータをスライドに載せて見せます.
このとき,実験データだけでなく実験をしている様子,動画を一緒に見せると説得力のあるいい発表となります.
また,データを見せるときはアニメーションで時間の流れを表現するとさらに良いです.
そこで,Processingでアニメーションを作成し動画も同時に見せる方法を解説します.
アニメーションの作り方は他の記事に譲るとして,ここではwebカメラの映像を表示する方法を解説します.
この記事を読むと以下のようなことがわかる・できるようになります.
- webカメラの映像をProcessingで表示する方法
- 3Dアニメーションにカメラの映像を重ねる方法
この記事を読む前に
この記事では3Dアニメーションにカメラの映像を重ねる方法も解説します.
そのためには以下の記事で解説している技術が必要になります.まだ読んでいない方は以下の記事を先に読んでおくことをおすすめします.
カメラの準備
まずはwebカメラを準備しましょう.
webカメラがなくてもパソコンにカメラが内蔵されている場合は問題ありません.
パソコンにカメラが内蔵されていなくて,webカメラも持っていないという方はキャプチャーボードを使ってデジカメなどの映像をパソコンで見られるようにするという手もあるらしいですが,試していないので真偽はわかりません.
私は以下のwebカメラを購入しました.
webカメラが先程届きました.Processingでカメラの映像を表示できるようにしたいと思います.これをすれば,プロジェクトが一つ終了にできます.https://t.co/LfNK8oGeka pic.twitter.com/kuVBtc4qUK
— おかしょ (@okasho_engineer) July 17, 2020
これで,ロボットの動きをProcessingに表示したいと思います.
接続されているカメラのリストを見る
まずはカメラがパソコンに正常につながっているかを確認します.
そのためのProcessingのプログラムが以下になります.
import processing.video.*;
int i = 0;
void setup(){
size(750, 500);
translate(width/4, height/10);
background(0);
String[] cam = Capture.list();
for(i=0; i<cam.length; i++)
{
textSize(20);
textAlign(RIGHT);
text("[" + i + "]", -10, i*25);
textAlign(LEFT);
text(cam[i], 0, i*25);
}
textAlign(RIGHT);
text("display width:", -10, (i+2)*25);
textAlign(LEFT);
text(displayWidth, 0, (i+1)*25+25);
textAlign(RIGHT);
text("display height:", -10, (i+3)*25);
textAlign(LEFT);
text(displayHeight, 0, (i+2)*25+25);
}
void draw()
{
}
おそらく,このプログラムを実行するとエラーが出ると思います.

最初にインクルードしているライブラリがまだ,インストールされていないことが原因です.
なので,エラーが出た時はライブラリのインストールを行いましょう.

Processingの上部に表示されている「スケッチ」>「ライブラリをインポート」>「ライブラリを追加…」の順にクリックします.

するとこのような「Contribution Manager」というウインドウが表示されます.
このウインドウの検索窓に「video」と入力します.
すると,以下のようにvideoに関するライブラリの一覧が表示されます.

その中の「Video| GStreamer-based video…」と書かれたライブラリを選択し「↓Install」をクリックします.
少し待つとライブラリのインストールが完了するので,完了したら先程のプログラムを再度実行します.

すると,このような画面が表示されます.
パソコンによっては表示されるまでに時間がかかるかもしれませんが,カメラが接続されていれば必ず文字が表示されますのでお待ちください.
私は1つのwebカメラしか接続していませんが,上記のように4つ表示されました.
その下にあるのは使用しているディスプレイのピクセル数です.
さて,ここで認識されたカメラが複数あるのは1つのカメラにつき複数のピクセル数で表示することが可能なためです.
ピクセル数が多ければ多いほど鮮明に映し出されますが,表示するまでに長い時間がかかってしまうので気を付けましょう.
この中から,Processingで表示するものを選択して使用します.
カメラの映像を表示する
カメラが接続できていることが確認できたので,Processingで表示してみます.
Processingでwebカメラの映像を表示するプログラムは以下になります.
import processing.video.*;
Capture cam;
void setup()
{
size(640,360);
String[] cameras = Capture.list();
cam = new Capture(this, 640, 360, cameras[0]);
cam.start();
}
void draw()
{
if(cam.available() == true){
cam.read();
}
image(cam, 0, 0);
}
簡単にプログラムの解説をすると,setup関数でカメラのリスト取得し使うカメラを選択して起動します.
その後,draw関数でカメラからの映像を更新しながら,表示を行います.
このプログラムを実行すると,以下のように映像が映し出されます.

3次元のアニメーションにカメラの映像を埋め込む
次に,3次元のアニメーションにカメラの映像を埋め込む方法を解説します.
このカメラの映像は2次元として描画されるので,3次元のアニメーションに埋め込む場合は工夫が必要です.
3次元のアニメーションにカメラの映像を埋め込んだプログラムは以下になります.
import processing.opengl.*;
import processing.video.*;
Capture cam;
float cameraX, cameraY, cameraZ;
void setup()
{
background(0); // 背景の色指定黒に指定
size(displayWidth,displayHeight, OPENGL); // windowのサイズを画面いっぱいにする
String[] cameras = Capture.list();
for(int i=0; i<cameras.length; i++){
println("[" + i + "] " + cameras[i]);
}
cam = new Capture(this, 640, 360, cameras[0]);
cam.start();
translate(width/2, height/2, 0); // 原点を画面の中心に
cameraX = 0.0;
cameraY = 10.0;
cameraZ = 250.0;
camera(cameraX, cameraY, cameraZ, 0.0, 0.0, 0.0, 0.0, 0.0, -1.0);
arrow(0, 0, 0, 150, 0, 0, 150, 0, 0);
arrow(0, 0, 0, 0, 150, 0, 0, 150, 0);
arrow(0, 0, 0, 0, 0, 150, 0, 0, 150);
}
void draw()
{
background(0); // 背景の色指定 黒に指定
if (keyPressed) {
if (keyCode == LEFT) cameraX -= 10;
if (keyCode == RIGHT) cameraX += 10;
if (keyCode == UP) cameraY -= 10;
if (keyCode == DOWN) cameraY += 10;
if (keyCode == CONTROL) cameraZ -= 10;
if (keyCode == SHIFT) cameraZ += 10;
}
camera(cameraX, cameraY, cameraZ, 0.0, 0.0, 0.0, 0.0, 0.0, -1.0);
stroke(50);
for(int i=-500; i<=500;)
{
line(-500, i, 0, 500, i, 0);
line(i, -500, 0, i, 500, 0);
i += 20;
}
arrow(0, 0, 0, 150, 0, 0, 150, 0, 0);
arrow(0, 0, 0, 0, 150, 0, 0, 150, 0);
arrow(0, 0, 0, 0, 0, 150, 0, 0, 150);
// 2次元描画
pushMatrix(); // 座標系の保存
rotateZ(-atan2(cameraX, cameraY));
rotateX(-atan2(sqrt(sq(cameraX)+sq(cameraY)), cameraZ));
translate(0, 0, sqrt(sq(cameraX)+sq(cameraY)+sq(cameraZ))-1000);
hint(DISABLE_DEPTH_TEST); // z軸を無効化
if(cam.available() == true){
cam.read();
}
rotate(PI/2);
translate(-500, -500);
image(cam, 0, 0);
hint(ENABLE_DEPTH_TEST); // z軸を有効化
popMatrix(); // 保存した座標系の出力
}
void cone(int L, float radius, int Color1, int Color2, int Color3)
{
float x, y;
noStroke();
fill(Color1, Color2, Color3);
beginShape(TRIANGLE_FAN); // 底面の円の作成
vertex(0, 0, -L);
for(float i=0; i<2*PI; )
{
x = radius*cos(i);
y = radius*sin(i);
vertex(x, y, -L);
i = i+0.01;
}
endShape(CLOSE);
beginShape(TRIANGLE_FAN); // 側面の作成
vertex(0, 0, 0);
for(float i=0; i<2*PI; )
{
x = radius*cos(i);
y = radius*sin(i);
vertex(x, y, -L);
i = i+0.01;
}
endShape(CLOSE);
}
void arrow(int x1, int y1, int z1, int x2, int y2, int z2, int Color1, int Color2, int Color3)
{
int arrowLength = 10;
float arrowAngle = 0.5;
float phi = -atan2(y2-y1, x2-x1);
float theta = PI/2-atan2(z2-z1, x2-x1);
stroke(Color1, Color2, Color3);
strokeWeight(4);
line(x1, y1, z1, x2, y2, z2);
strokeWeight(1);
pushMatrix();
translate(x2, y2, z2);
rotateY(theta);
rotateX(phi);
cone(arrowLength, arrowLength*sin(arrowAngle), Color1, Color2, Color3);
popMatrix();
}
このプログラムでは視点の変更がキーボードの操作でできるようになっています.
詳しくはこちらを参照してください.
このプログラムによって,以下のように表示されます.

このように視点を変更しても,問題なくカメラの映像が表示できています.
この視点を変更しても2次元の図形を問題なく表示する方法はこちらを参照してください.
また,カメラの映像のサイズは56行目の数値,表示される位置は61行目で調整ができます.
まとめ

この記事ではwebカメラの映像をProcessingで表示する方法を解説しました.
3次元のアニメーションにも埋め込めるようにするプログラムも公開しました.
今回公開したプログラムを利用することで,学会などで利用しても説得力のある発表ができるようになります.
続けて読む
以下の記事では姿勢角の算出方法の比較を行うアニメーションの解説をしています.
実際の姿勢角もわかるようにするために,今回解説したカメラ映像の表示方法も使用しています.
興味のある方は続けて読んでみてください.
Twitterでは記事の更新情報や活動の進捗などをつぶやいているので気が向いたらフォローしてください.
それでは最後まで読んでいただきありがとうございました.
コメント