人が動いた後にいろいろなエフェクトがかかるサンプル。
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 102 103 104 105 106 107 108 109 110 111 | import processing.video.*; Capture video; //キャプチャ用変数 int[] previousFrame; //一つ前のフレーム int pixelNum; //キャプチャ画面の総ピクセル数 int noiseFilter = 50; //ノイズを拾わないためのフィルタ(値を増やすとフィルタが強くかかる) int reduction = 8; //画面に対してのキャプチャ映像の縮小度合い 8の場合は、キャプチャ画像が画面の1/8という意味になる int movementSum; //一つのフレームでの動作量 float[] eSize; //円のサイズ float[] eSpeed; //円の拡大のスピード float[] eAlpha; //円の透明度 float[] eAlphaSpeed; //円の透明度のスピード int[] eFlag; //円の透明度が0になったかどうかを判断するためのフラッグ void setup() { // 640 x 480が大きすぎて遅かったら、320 x 240に変更する size(640, 480); //画面サイズのキャプチャ画像を生成。画面がコマ落ちするようだったら、 //一番右のフレームレートを上げる。 //この場合は、80x60のキャプチャ画像、90フレーム/秒を設定 video = new Capture(this, width/reduction, height/reduction, 90); pixelNum = video.width * video.height; //キャプチャ画像の総ピクセル数 previousFrame = new int[pixelNum]; //一つ前のフレーム(配列) eSize = new float[pixelNum]; //円の大きさ eSpeed = new float[pixelNum]; //円の拡大スピード eAlpha = new float[pixelNum]; //円の透明度 eAlphaSpeed = new float[pixelNum]; //円の透明化のスピード eFlag = new int[pixelNum]; //円が表示されている状態かそうでないかを判断するフラッグ //円の属性の初期化 for(int i = 0; i < pixelNum; i ++){ eSize[i] = 0.0; eSpeed[i] = 1.0; eAlpha[i] = 200.0; eAlphaSpeed[i] = 2.0; eFlag[i] = 0; } loadPixels(); //画面に画像のピクセルを展開 } void draw() { background(0); float m = millis(); //時間をカウント if (video.available()) { //もしキャプチャができたら、 video.read(); //ビデオフレームの読み込み video.loadPixels(); //ビデオのピクセルを操作できるようにする movementSum = 0; //一つのフレームでの動作量 //1ピクセルごとに色を調べる。 for (int y = 0; y < video.height; y ++) { for (int x = 0; x < video.width; x ++) { //ビデオのピクセルを抜き出す int currColor = video.pixels[y*video.width + x]; int prevColor = previousFrame[y*video.width + x]; //現在のピクセルのR, G, Bを抜き出す int currR = (currColor >> 16) & 0xFF; int currG = (currColor >> 8 ) & 0xFF; int currB = currColor & 0xFF; //一つ前のフレームの色を抜き出す int prevR = (prevColor >> 16) & 0xFF; int prevG = (prevColor >> 8 ) & 0xFF; int prevB = prevColor & 0xFF; //現在のピクセルから前のピクセルの色を引いた絶対値 int diffR = abs(currR - prevR); int diffG = abs(currG - prevG); int diffB = abs(currB - prevB); //noiseFilterの値よりも大きかったらmovementSumに足していく //そして、現在の色に更新 //以下の条件文は3秒後に有効になる if(diffR + diffG + diffB > noiseFilter && eFlag[y*video.width + x] == 0 && m > 3*1000){ eFlag[y*video.width + x] = 1; //フラッグを1にする(円が再生中) movementSum ++; //以下の4行のコードは動いたところにラインを発生させるコードである(左右を反転させている) float lineSize = (float)(diffR + diffG + diffB)/(255*3)*20.0; stroke(currR, 100, 255, 80); line(((video.width-x)-lineSize)*reduction, y*reduction, ((video.width-x)+lineSize)*reduction, y*reduction); stroke(255, 100, currB, 80); line((video.width-x)*reduction, (y-lineSize/2)*reduction, (video.width-x)*reduction, (y+lineSize/2)*reduction); } //透明度(Alpha)が0.0未満にならない限りは、円はひたすら大きくなり、透明度はひたすら下がる if(eFlag[y*video.width + x] == 1 && eAlpha[y*video.width + x] >= 0.0){ eSize[y*video.width + x] += eSpeed[y*video.width + x]; eAlpha[y*video.width + x] -= eAlphaSpeed[y*video.width + x]; noStroke(); fill(currR, currG, currB, (int)(eAlpha[y*video.width + x])); ellipse((video.width-x)*reduction, y*reduction, eSize[y*video.width + x], eSize[y*video.width + x]); } //透明度(Alpha)が0.0未満になったら、円の属性をリセットする else if(eFlag[y*video.width + x] == 1 && eAlpha[y*video.width + x] < 0.0){ eSize[y*video.width + x] = 0.0; eAlpha[y*video.width + x] = 100.0; eFlag[y*video.width + x] = 0; } previousFrame[y*video.width + x] = currColor; //現在の色を一つ前のフレームの色として保存 } } textSize(12); //テキストのサイズ fill(255); text(movementSum, 30,30); //変化したピクセルの総数を画面にプリント } } |