さて、次はオープンソースの画像処理ライブラリである、OpenCVを使ってみます。
元のOpenCVはC++用に書かれていて、ここで使うものはProcessing用に機能を限定したものです。
ですが、それでも使いようによっては便利な機能があるので、ある程度の細かい画像処理ができます。
インストール
まずは、OpenCVをインストールします。以下のページを開いてください。ここには、processingで使える機能も全て出ています。
http://ubaa.net/shared/processing/opencv/
このページの上の方にある、opencv-framework-1.1.dmgをダウンロードし、インストールします。
ミラーサーバ
次に、OpenCV Processing Libraryをダウンロードし、ProcessingのLibrariesフォルダに入れましょう(下図を参照して下さい。)
サンプルが欲しい人は以下のリンクからダウンロードしてください。
OpenCV processing examples
そして、Processingを再起動しましょう。
最初のプログラム
まずは、簡単なサンプルをやってみましょう。
一定のしきい値によって白黒に表示するプログラムです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | import hypermedia.video.*; //ライブラリを使う OpenCV opencv; //OpenCV型の変数を宣言 void setup() { size( 640, 480 ); // open video stream opencv = new OpenCV( this ); opencv.capture( 640, 480 ); //キャプチャを行う } void draw() { opencv.read(); //カメラから映像を取り込む opencv.convert(OpenCV.GRAY); //グレーに変更する opencv.threshold(80); //80から255までの間を白にする image( opencv.image(), 0, 0 ); //映像を表示する。0, 0は映像の左上座標 } |
どうでしょうか?既に行った実習でも似たようなことをしましたが、それよりもかなり簡単にできたと感じたのではないでしょうか?
flip
次は、映像の反転です。これも先週やりましたよね?今度はもっと簡単です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | import hypermedia.video.*; //ライブラリを使う OpenCV opencv; //OpenCV型の変数を宣言 void setup() { size( 640, 240 ); opencv = new OpenCV(this); opencv.capture( 320, 240 ); //キャプチャを行う } void draw() { opencv.read(); opencv.flip( OpenCV.FLIP_BOTH ); //上下左右を反転させる //ビデオの表示 image( opencv.image(OpenCV.SOURCE), 0, 0 ); //元映像 image( opencv.image(), 320, 0 ); //反転された映像 } |
上記では、opencv.flip( OpenCV.FLIP_BOTH );となっていて、上下左右を反転させる設定になっています。3つのモードがあります。FLIP_HORIZONTAL(左右反転)、FLIP_VERTICAL(上下反転)、 FLIP_BOTH(上下左右反転)の3種類があります。
フレーム差分
フレーム差分も先ほどやりましたが、このコードもかなり短くなってます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | import hypermedia.video.*; //ライブラリを使う OpenCV opencv; //OpenCV型の変数を宣言 void setup() { size( 640, 480 ); opencv = new OpenCV(this); opencv.capture( 320, 240 ); //キャプチャを行う } void draw() { opencv.read(); //カメラから映像を取り込む image( opencv.image(), 0, 0); //元映像 opencv.absDiff(); //現在の映像と保存された画像を比較する image( opencv.image(OpenCV.MEMORY), 320, 0 ); //保存された画像を右上に表示 image( opencv.image(), 320, 240 ); //結果を右下に表示 } void keyPressed() { opencv.remember(); //画像を保存する } |
物体の認識(トラッキング)
さて、一番難しいトラッキングです。
サンプルを用意してみたので、参考にしてみましょう。詳細は授業中に触れます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 | import java.awt.Rectangle; import java.awt.Point; import hypermedia.video.*; OpenCV opencv; int w = 320; int h = 240; int threshold = 80; boolean find=true; PFont font; void setup() { size( w*2, h); opencv = new OpenCV( this ); //OpenCVを使うことを宣言する opencv.capture(w,h); //w x hのサイズのキャプチャ映像を取り込む(この場合、320 x 240) font = createFont("Monaco", 9); textFont(font); println( "Drag mouse inside sketch window to change threshold" ); println( "Press space bar to record background image" ); } void draw() { background(0); opencv.read(); //image( opencv.image(), 0, 0); //元映像 opencv.absDiff(); opencv.threshold(threshold); image( opencv.image(), 0, 0); // 背景画像とキャプチャ映像の差 // blobの作成 //blobs(最小ピクセル、最大ピクセル、blobの最大数、穴の空いたblobがあるか) Blob[] blobs = opencv.blobs( 100, w*h/3, 20, true ); noFill(); translate(320, 0); //blobの数を数える for( int i = 0; i < blobs.length; i ++ ) { Rectangle bounding_rect = blobs[i].rectangle; //blobを囲った四角形 float area = blobs[i].area; //面積 float circumference = blobs[i].length; //外周 Point centroid = blobs[i].centroid; //blobの中心点 Point[] points = blobs[i].points; //blobの構成点 //四角形 noFill(); //blobが穴であるかどうかを判断し、穴だったら白、そうでなかったら暗いグレーの四角形を作成 if(blobs[i].isHole == true) stroke(255); else stroke(64); //blobの周辺の四角を描画 rect( bounding_rect.x, bounding_rect.y, bounding_rect.width, bounding_rect.height ); //blobの中心を描画 stroke(0,0,255); line( centroid.x-5, centroid.y, centroid.x+5, centroid.y ); //中心から水平線を描画 line( centroid.x, centroid.y-5, centroid.x, centroid.y+5 ); //中心から垂直線を描画 noStroke(); fill(0,0,255); text( area,centroid.x+5, centroid.y+5 ); //面積を表示 //オブジェクトの境界を描画し、その中を塗りつぶす fill(255,0,255,64); stroke(255,0,255); if ( points.length>0 ) { beginShape(); for( int j = 0; j < points.length; j ++ ) { vertex( points[j].x, points[j].y ); } endShape(CLOSE); } //オブジェクトの外周を表示 noStroke(); fill(255,0,255); text( circumference, centroid.x+5, centroid.y+15 ); } } //スペースキーが押された時に画像を記憶する。 void mousePressed() { opencv.remember(); } public void stop() { opencv.stop(); super.stop(); } //注意!!!!! //Processingのバージョンが1.1の場合は、下記の2行を冒頭に追加する。 //import java.awt.Rectangle; //import java.awt.Point; |
Pingback: OpenCVことはじめ : circumstance evidence