Eye pod touch

Eye pod touch

ただの覚え書き

Amebaでブログを始めよう!

Processingエフェクト


この間のProcessingのエフェクトを作ったやつの続きで、ついでに波紋のエフェクトとフェードのエフェクトを作りました。

EffectManagerに登録すればOK。mousePressedでWaveEffectにmouseX,mouseYを渡せば、クリックしたところからふわぁっと波が広がります。

Eye pod touch-wave

ソースコード


WaveEffectクラス


public class WaveEffect extends Effect{
private int time=0;
private float r1=0;
private float r2=0;
private color c;
private int weight=1;
private float speed;
private float radius=0;
private final int rate=5;

/**

@param r1 inner radius
@param r2 outer radius,effect area
*/
public WaveEffect(int x,int y,float r1,float r2,int weight,color c,float limit,int fRate){
super(x,y,limit,fRate);
this.r1=r1;
this.r2=r2;
this.c=c;
this.weight=weight;
this.speed=r2/(limit*fRate);
}

/**
draw method.
@return isLiving
*/
public boolean draw(){
if(time>limit*fRate){
return false;
}

//draw
float r;
if(radius>r1){
r=r2/radius*rate;
}else{
r=rate;
}
float rSpeed=this.speed*r;
radius+=rSpeed;
stroke(c);
strokeWeight(this.weight);
noFill();
ellipse(x,y,radius,radius);

time++;
return true;
}
}

FadeoutScreenEffectクラス


public class FadeoutScreenEffect extends Effect{
private int w;
private int h;
private int time=0;
private int inTime;
private int outTime;
private float inSpeed;
private float outSpeed;
private color c;
private float alpha=0;

public FadeoutScreenEffect(int x,int y,color c,int w,int h,float inTime,float outTime,int fRate){
super(x,y,inTime+outTime,fRate);
this.inTime=(int)inTime*fRate;
this.outTime=(int)outTime*fRate;
this.c=c;
this.w=w;
this.h=h;
this.inSpeed=255.0/this.inTime;
this.outSpeed=-255.0/this.outTime;
//println("inSpeed:"+this.inSpeed+",outSpeed:"+this.outSpeed+"inTime:"+this.inTime+",outTime:"+this.outTime);
}

/**
draw method.
@return isLiving
*/
public boolean draw(){
if(time>limit*fRate){
return false;
}

//draw
if(time alpha+=inSpeed;
if(alpha>=255){
alpha=255;
}
}else{
alpha+=outSpeed;
if(alpha<=0){
alpha=0;
}
}
int r=(int)red(c);
int g=(int)green(c);
int b=(int)blue(c);
stroke(r,g,b,(int)alpha);
fill(r,g,b,(int)alpha);
rect(x,y,w,h);
//println("alpha:"+alpha+",inSpeed:"+inSpeed+",outSpeed:"+outSpeed+"inTime:"+inTime+",outTime:"+outTime);

time++;
return true;
}

}


本当はProcessingで爆発エフェクト的なものを作りたかったのですが。。。なんか違う。
filterでBLURをかければそれっぽくなるのですが、背景には別の描画をする予定で、エフェクトだけBLURをかけようとするとPGraphicsで新しく画面つくって一度そこに描画したものをimageで描画して……なんていうダブルバッファリングみたいなことをしていると動作がもっさりしたのでやめました。


現状はただの花火です。クリックしたところから炸裂します。


Eye pod touch-fireflower

ソースコード


Mainクラス



private EffectManager effManager;
private PShader blur;

public void setup() {
size(400, 400);
effManager=new EffectManager(width,height);
smooth();
} // frameRate はデフォルト値に設定される

public void draw() {
background(128, 128, 128);
effManager.draw();
}

public void mousePressed() { // マウスボタンが押下された際に呼び出される
if (mouseButton == LEFT){ // 左ボタンであれば
effManager.addEffect(new ExplosionEffect(mouseX,mouseY,100,100,3.0,(int)frameRate));
}
}

EffectManagerクラス



public class EffectManager{
private ArrayList effectList=new ArrayList();
private int w=width;
private int h=height;

public EffectManager(int w,int h){
setSize(w,h);
}

public void setSize(int w,int h){
this.w=w;
this.h=h;
}

public void addEffect(Effect eff){
effectList.add(eff);
}

public void draw(){
for(int i=0;i Effect eff=effectList.get(i);
boolean isEnd=!eff.draw();
if(isEnd){
println("DEAD");
removeEffect(eff,i);
}
}
}

private void removeEffect(Effect eff,int index){
effectList.remove(index);
}
}

Effectクラス


public abstract class Effect{
protected int x=0;
protected int y=0;
protected float limit=0;
protected int fRate=0;

public Effect(){
}
public Effect(int x,int y,float limit,int fRate){
setX(x);
setY(y);
this.limit=limit;
this.fRate=fRate;
}

public void setX(int x){
this.x=x;
}
public void setY(int y){
this.y=y;
}
public void setfRate(int fRate){
this.fRate=fRate;
}


public abstract boolean draw();
}

ExplosionEffectクラス


public class ExplosionEffect extends Effect{
private Particle pars[];
private int time=0;
private int r;
private final int parSize=5;

public ExplosionEffect(int x,int y,int r,int pNum,color c,float limit,int fRate){
super(x,y,limit,fRate);
this.r=r;
pars=new Particle[pNum];
for(int i=0;i int pSize=(int)(parSize*random(0.5,3));
int pLife=(int)(limit*fRate*random(0.5,1));
float pSpeed=random(r/(limit*fRate));
pars[i]=new Particle(x+(int)random(-30,30),y+(int)random(-30,30),pSize,c,pLife,pSpeed,random(0,2*PI));
}
}

public ExplosionEffect(int x,int y,int r,int pNum,float limit,int fRate){
super(x,y,limit,fRate);
this.r=r;
pars=new Particle[pNum];
for(int i=0;i int pSize=(int)(parSize*0.75+parSize*random(0.5));
int pLife=(int)(limit*fRate*0.5+limit*fRate*random(0.5));
float pSpeed=random(r/(limit*fRate));
color c=color(255,128+(int)random(128),0);
pars[i]=new Particle(x,y,pSize,c,pLife,pSpeed,random(0,2*PI));
}
}


/**
draw method.
@return isLiving
*/
public boolean draw(){
if(time>limit*fRate){
return false;
}

//draw
boolean isLiving=false;
for(Particle p:pars){
if(p.draw()){
isLiving=true;
}
}
//pg.filter(BLUR, 1);

if(!isLiving){//isAllDead
time=(int)limit*fRate;
}
time++;
return true;
}
}

Particleクラス


public class Particle{
private float x;
private float y;
private int r;
private int lifeTime;
private float speed;
private float angle;//radian
private color c;

public Particle(float x,float y,int r,color c,int lifeTime,float speed,float angle){
this.x=x;
this.y=y;
this.r=r;
this.c=c;
this.lifeTime=lifeTime;
setSpeed(speed);
setAngle(angle);
}

//setter
public void setSpeed(float s){
this.speed=s;
}
public void setAngle(float angle){
this.angle=angle;
}
public void setX(float x){
this.x=x;
}
public void setY(float y){
this.y=y;
}

//getter
public float getSpeed(){
return this.speed;
}
public float getAngle(){
return this.angle;
}

/**
draw Method
@return isLiving:true
*/
public boolean draw(){
if(lifeTime>0){
stroke(c);
fill(c);
//System.out.println(red(c)+green(c)+blue(c));
ellipse((int)x,(int)y,r,r);

//move
x+=speed*cos(angle);
y+=speed*sin(angle);
//println("x:"+x+",y:"+y+",speed:"+speed+",life:"+lifeTime);

//life
lifeTime--;
return true;
}
return false;
}
}

RaspberryPiでOpenCVを触ってみました。

大学の講義の課題でSIFTとSURFの特徴点の対応付けをするというものがあったので、やってみました。


準備



  • RaspberryPi

  • 適当な画像2枚(同じ場所・物を別角度から撮ったもの)


OpenCVをインストール(インストールされるのはOpenCV2.3)


$ sudo apt-get install libopencv-dev

サンプル画像


Eye pod touch-img00Eye pod touch-img01

SIFT


画像処理 — OpenCV-CookBookのサンプルを参考にした。


#include 
#include
#include
#include

#define OPENCV_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
#define OPENCV_VERSION_CODE OPENCV_VERSION(CV_MAJOR_VERSION, CV_MINOR_VERSION, CV_SUBMINOR_VERSION)

#if OPENCV_VERSION_CODE>=OPENCV_VERSION(2,4,0)
#include
#endif

int main(int argc, char *argv[])
{
if(argc!=4){
std::cout << "This program need 4 arguments!" << std::endl;
return 0;
}

double threshold = cv::SIFT::DetectorParams::GET_DEFAULT_THRESHOLD();
double edge_threshold = cv::SIFT::DetectorParams::GET_DEFAULT_EDGE_THRESHOLD();
double magnification = cv::SIFT::DescriptorParams::GET_DEFAULT_MAGNIFICATION();

std::cout << "threshold = " << threshold << std::endl;
std::cout << "edge_threshold = " << threshold << std::endl;
std::cout << "magnification = " << magnification << std::endl;
std::cout << "now processing..." << std::endl;

cv::Mat img1 = cv::imread(argv[1], 1);
if(img1.empty()) return -1;
cv::Mat img2 = cv::imread(argv[2], 1);
if(img2.empty()) return -1;

cv::Mat gray_img1, gray_img2;
cv::cvtColor(img1, gray_img1, CV_BGR2GRAY);
cv::cvtColor(img2, gray_img2, CV_BGR2GRAY);
cv::normalize(gray_img1, gray_img1, 0, 255, cv::NORM_MINMAX);
cv::normalize(gray_img2, gray_img2, 0, 255, cv::NORM_MINMAX);

std::vector keypoints1, keypoints2;
std::vector::iterator itk;
cv::Mat descriptors1, descriptors2;

// SIFT
cv::SiftFeatureDetector detector(threshold,edge_threshold);
detector.detect(gray_img1, keypoints1);
detector.detect(gray_img2, keypoints2);
// SIFT に基づくディスクリプタ抽出器
cv::SiftDescriptorExtractor extractor(magnification);
cv::Scalar color(100,255,50);
extractor.compute(gray_img1, keypoints1, descriptors1);
extractor.compute(gray_img2, keypoints2, descriptors2);

// FlannBasedMatcher によるマッチ
cv::FlannBasedMatcher matcher;
std::vector matches;
matcher.match(descriptors1, descriptors2, matches);

// マッチング結果の描画
cv::Mat dst_img;
cv::drawMatches(img1, keypoints1, img2, keypoints2, matches, dst_img);

//cv::namedWindow("Match", CV_WINDOW_AUTOSIZE|CV_WINDOW_FREERATIO);
//cv::imshow("Match", dst_img);
cv::imwrite(argv[3],dst_img);
std::cout << "Done." << std::endl;
std::cout << "OutImage:" << argv[3] << std::endl;
cv::waitKey(0);
}

出力サンプル


$Eye pod touch-SIFT

SURF


上と同様。一部を変更しただけ。


#include 
#include
#include
#include

#define OPENCV_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
#define OPENCV_VERSION_CODE OPENCV_VERSION(CV_MAJOR_VERSION, CV_MINOR_VERSION, CV_SUBMINOR_VERSION)

#if OPENCV_VERSION_CODE>=OPENCV_VERSION(2,4,0)
#include
#endif

int
main(int argc, char *argv[])
{
if(argc!=4){
std::cout << "This program need 4 arguments!" << std::endl;
return 0;
}
double threshold = 2000;
std::cout << "threshold = " << threshold << std::endl;
std::cout << "now processing..." << std::endl;
cv::Mat img1 = cv::imread(argv[1], 1);
if(img1.empty()) return -1;
cv::Mat img2 = cv::imread(argv[2], 1);
if(img2.empty()) return -1;

cv::Mat gray_img1, gray_img2;
cv::cvtColor(img1, gray_img1, CV_BGR2GRAY);
cv::cvtColor(img2, gray_img2, CV_BGR2GRAY);
cv::normalize(gray_img1, gray_img1, 0, 255, cv::NORM_MINMAX);
cv::normalize(gray_img2, gray_img2, 0, 255, cv::NORM_MINMAX);

std::vector keypoints1, keypoints2;
std::vector::iterator itk;
cv::Mat descriptors1, descriptors2;

// SURF
// ex:threshold=2000
cv::SurfFeatureDetector detector(threshold);
detector.detect(gray_img1, keypoints1);
detector.detect(gray_img2, keypoints2);
// SURF に基づくディスクリプタ抽出器
cv::SurfDescriptorExtractor extractor;
cv::Scalar color(100,255,50);
extractor.compute(gray_img1, keypoints1, descriptors1);
extractor.compute(gray_img2, keypoints2, descriptors2);

// FlannBasedMatcher によるマッチ
cv::FlannBasedMatcher matcher;
std::vector matches;
matcher.match(descriptors1, descriptors2, matches);

// マッチング結果の描画
cv::Mat dst_img;
cv::drawMatches(img1, keypoints1, img2, keypoints2, matches, dst_img);

//cv::namedWindow("Match", CV_WINDOW_AUTOSIZE|CV_WINDOW_FREERATIO);
//cv::imshow("Match", dst_img);
cv::imwrite(argv[3],dst_img);
std::cout << "Done."<< std::endl;
std::cout << "OutImage:"<< argv[3] << std::endl;
cv::waitKey(0);
}

出力サンプル


$Eye pod touch-SURF

デスクトップ環境でOpenCVの処理をさせるのはRaspberryPiのスペックだときついので(場合によっては落ちる)、CUI環境(sshとか)でやったほうがいい。