次回11/25の授業は引き続きWebカメラを用いて、動体検知の実験をします。
時間があれば、カメラをセンサーにして、接続されたArduinoと連動させたいと思います。
必要なもの:
・ノートパソコン
・Webカメラ(ノートパソコン内蔵型も可)
・Arduinoボード類
サンプル1(Processing):カメラがとらえた画面中で動くもの(画面に変化がある部分)を察知して、その動いている部分の平均座標値を求めて、その位置に円を描くサンプル。変数toleranceは、色の許容値なので、上げればより鈍く、下げればより敏感に反応します。
import processing.video.*;
Capture video;
int w=320;
int h=240;
color[] exColor=new color[w*h];
float x,y;
int sumX,sumY;
int pixelNum;
boolean movement=false;
int tolerance=40;
void setup(){
size(320, 240);
video = new Capture(this, w, h);
video.start();
noStroke();
}
void draw() {
if(video.available()){
background(0);
video.read();
set(0,0,video);
loadPixels();
movement=false;
for(int i=0;i<w*h;i++){
float difRed=abs(red(exColor[i])-red(video.pixels[i]));
float difGreen=abs(green(exColor[i])-green(video.pixels[i]));
float difBlue=abs(blue(exColor[i])-blue(video.pixels[i]));
if(difRed>tolerance && difGreen>tolerance && difBlue>tolerance){
movement=true;
pixels[i]=color(0,255,0);
sumX+=i%w;
sumY+=i/w;
pixelNum++;
}
exColor[i]=video.pixels[i];
}
updatePixels();
if(movement==true){
x=sumX/pixelNum;
y=sumY/pixelNum;
sumX=0;
sumY=0;
pixelNum=0;
}
}
fill(255,0,0);
ellipse(x,y,20,20);
fill(0,40,255);
}
サンプル2(Arduino):
動きを検知したProcessingのプログラムに対して、シリアル通信でArduinoと連結し、サーボモータを動かすサンプル。Processing上の動くオブジェクトのX座標(横の動き)に対して、サーボモータの首振りの角度が対応しています。
#include <Servo.h>
Servo myServo;
void setup(){
Serial.begin(9600);
myServo.attach(9);
}
void loop(){
if(Serial.available()>0){
int val=Serial.read();
int x=map(val,0,255,0, 179);
myServo.write(x);
}
delay(15);
}
サンプル2(Processing):上記サーボモータをつないだArduinoに対するProcessing側のサンプルです。Processindgサンプル1の内容に変数float x2,y2を加えてlerp()をつかうことで、円の動きをやや滑らかにする計算をさせています。
import processing.video.*;
Capture video;
import processing.serial.*;
Serial myPort;
int w=320;
int h=240;
color[] exColor=new color[w*h];
float x,y;
float x2,y2;
int sumX,sumY;
int pixelNum;
boolean movement=false;
int tolerance=40;
void setup(){
size(w, h);
video = new Capture(this, w, h);
video.start();
noStroke();
myPort=new Serial(this,"/dev/tty.usbserial-A9005baQ",9600);
//上記"/dev/tty.usbserial-A9005baQ"の部分には各自のシリアルポートをいれてください
}
void draw() {
if(video.available()){
background(0);
video.read();
set(0,0,video);
loadPixels();
movement=false;
for(int i=0;i<w*h;i++){
float difRed=abs(red(exColor[i])-red(video.pixels[i]));
float difGreen=abs(green(exColor[i])-green(video.pixels[i]));
float difBlue=abs(blue(exColor[i])-blue(video.pixels[i]));
if(difRed>tolerance && difGreen>tolerance && difBlue>tolerance){
movement=true;
pixels[i]=color(0,255,0);
sumX+=i%w;
sumY+=i/w;
pixelNum++;
}
exColor[i]=video.pixels[i];
}
updatePixels();
if(movement==true){
x=sumX/pixelNum;
y=sumY/pixelNum;
sumX=0;
sumY=0;
pixelNum=0;
}
}
fill(255,0,0);
//ellipse(x,y,20,20);
//myPort.write(int(map(x,0,width,0,255)));
x2=lerp(x,x2,0.9);
y2=lerp(y,y2,0.9);
ellipse(x2,y2,20,20);
myPort.write(int(map(x2,0,width,0,255)));
fill(0,40,255);
}
サンプル1(Processing):カメラがとらえた画面中で動くもの(画面に変化がある部分)を察知して、その動いている部分の平均座標値を求めて、その位置に円を描くサンプル。変数toleranceは、色の許容値なので、上げればより鈍く、下げればより敏感に反応します。
import processing.video.*;
Capture video;
int w=320;
int h=240;
color[] exColor=new color[w*h];
float x,y;
int sumX,sumY;
int pixelNum;
boolean movement=false;
int tolerance=40;
void setup(){
size(320, 240);
video = new Capture(this, w, h);
video.start();
noStroke();
}
void draw() {
if(video.available()){
background(0);
video.read();
set(0,0,video);
loadPixels();
movement=false;
for(int i=0;i<w*h;i++){
float difRed=abs(red(exColor[i])-red(video.pixels[i]));
float difGreen=abs(green(exColor[i])-green(video.pixels[i]));
float difBlue=abs(blue(exColor[i])-blue(video.pixels[i]));
if(difRed>tolerance && difGreen>tolerance && difBlue>tolerance){
movement=true;
pixels[i]=color(0,255,0);
sumX+=i%w;
sumY+=i/w;
pixelNum++;
}
exColor[i]=video.pixels[i];
}
updatePixels();
if(movement==true){
x=sumX/pixelNum;
y=sumY/pixelNum;
sumX=0;
sumY=0;
pixelNum=0;
}
}
fill(255,0,0);
ellipse(x,y,20,20);
fill(0,40,255);
}
サンプル2(Arduino):
動きを検知したProcessingのプログラムに対して、シリアル通信でArduinoと連結し、サーボモータを動かすサンプル。Processing上の動くオブジェクトのX座標(横の動き)に対して、サーボモータの首振りの角度が対応しています。
#include <Servo.h>
Servo myServo;
void setup(){
Serial.begin(9600);
myServo.attach(9);
}
void loop(){
if(Serial.available()>0){
int val=Serial.read();
int x=map(val,0,255,0, 179);
myServo.write(x);
}
delay(15);
}
サンプル2(Processing):上記サーボモータをつないだArduinoに対するProcessing側のサンプルです。Processindgサンプル1の内容に変数float x2,y2を加えてlerp()をつかうことで、円の動きをやや滑らかにする計算をさせています。
import processing.video.*;
Capture video;
import processing.serial.*;
Serial myPort;
int w=320;
int h=240;
color[] exColor=new color[w*h];
float x,y;
float x2,y2;
int sumX,sumY;
int pixelNum;
boolean movement=false;
int tolerance=40;
void setup(){
size(w, h);
video = new Capture(this, w, h);
video.start();
noStroke();
myPort=new Serial(this,"/dev/tty.usbserial-A9005baQ",9600);
//上記"/dev/tty.usbserial-A9005baQ"の部分には各自のシリアルポートをいれてください
}
void draw() {
if(video.available()){
background(0);
video.read();
set(0,0,video);
loadPixels();
movement=false;
for(int i=0;i<w*h;i++){
float difRed=abs(red(exColor[i])-red(video.pixels[i]));
float difGreen=abs(green(exColor[i])-green(video.pixels[i]));
float difBlue=abs(blue(exColor[i])-blue(video.pixels[i]));
if(difRed>tolerance && difGreen>tolerance && difBlue>tolerance){
movement=true;
pixels[i]=color(0,255,0);
sumX+=i%w;
sumY+=i/w;
pixelNum++;
}
exColor[i]=video.pixels[i];
}
updatePixels();
if(movement==true){
x=sumX/pixelNum;
y=sumY/pixelNum;
sumX=0;
sumY=0;
pixelNum=0;
}
}
fill(255,0,0);
//ellipse(x,y,20,20);
//myPort.write(int(map(x,0,width,0,255)));
x2=lerp(x,x2,0.9);
y2=lerp(y,y2,0.9);
ellipse(x2,y2,20,20);
myPort.write(int(map(x2,0,width,0,255)));
fill(0,40,255);
}