@joana
Since I do not have a PC, I adapted the code to be able to work with the android Ketai library. I still not have the quality of the original video. In the video below I am waving a golden brush in front of my phone camara, but it is barely noticeable. I will tweak a bit to see what happens. Please post your result also.
/**
ParticleVideo by Dan Bridges 2011
Check out Daniel Shiffman's tutorials on
particle systems here:
http://www.shiffman.net/teaching/nature/particles/
As you can see some of this code is built upon
those tutorials.
*/
import ketai.camera.*;
KetaiCamera cam;
PImage prevFrame;
float threshold = 50;
int videoWidth;
int videoHeight;
int reduction;
ParticleSystem system;
void setup() {
size(320, 240);
system = new ParticleSystem(30000);
frameRate(30);
reduction = 1;
videoWidth = width/reduction;
videoHeight = height/reduction;
cam = new KetaiCamera(this, 320, 240, 20);
cam.start();
prevFrame = createImage(cam.width, cam.height, RGB);
}
void onCameraPreviewEvent() {
prevFrame.copy(cam, 0, 0, cam.width, cam.height, 0, 0, cam.width, cam.height);
prevFrame.updatePixels();
cam.read();
}
void draw() {
// image(cam, 0, 0);
background(255,200);
cam.loadPixels();
prevFrame.loadPixels();
for (int x=0; x< videoWidth; x+=3) {
for (int y = 0; y < videoHeight; y+=4) {
if (abs((cam.pixels[y* videoWidth +x] >> 16 & 0xFF)-(prevFrame.pixels[y* videoWidth +x] >> 16 & 0xFF)) < 75
&& abs((cam.pixels[y* videoWidth +x] >> 8 & 0xFF)-(prevFrame.pixels[y* videoWidth +x] >> 8 & 0xFF)) < 75
&& abs((cam.pixels[y* videoWidth +x] & 0xFF)-(prevFrame.pixels[y* videoWidth +x] & 0xFF)) < 75) {
} else {
for (int i=0; i<2; i++) {
system.addParticle(( videoWidth - x - 1)*reduction, y*reduction, random(-100, 100), random(-320, 0), 1);
}
}
}
}
system.update(1/frameRate, cam);
fill(0);
}
public class ParticleSystem {
private ArrayList <Particle> particles;
private int iterations;
private int maxSize;
ParticleSystem(int maxSize) {
this.particles = new ArrayList<Particle>(maxSize);
this.iterations = 1;
this.maxSize = maxSize;
}
void update(float dt, KetaiCamera cam ) {
for (int j = particles.size()-1; j >= 0; j--) {
Particle particle = particles.get(j);
particle.update(dt);
if (particle.position.x > 0 && particle.position.x < width &&
particle.position.y > 0 && particle.position.y < height) {
particle.render(cam.pixels[floor(particle.position.y/reduction)*videoWidth+(videoWidth-floor(particle.position.x/reduction)-1)]);
}
if (particle.shouldDestroy()) {
particles.remove(j);
}
}
}
void addParticle(float x, float y, float mass) {
this.addParticle(x, y, 0, 0, mass);
}
void addParticle(float x, float y, float dx, float dy, float mass) {
if (size() < maxSize) {
particles.add(new Particle(x, y, dx, dy, mass));
}
}
int size() {
return particles.size();
}
}
public class Particle {
private PVector position;
private PVector velocity;
private PVector force;
private float mass;
private boolean fixed;
private float diameter;
private float time;
private float maxTime;
Particle(float x, float y, float mass) {
this(x, y, 0.0, 0.0, mass);
}
Particle(float x, float y, float dx, float dy, float mass) {
this.position = new PVector(x, y);
this.velocity = new PVector(dx, dy);
this.force = new PVector(0, 0);
this.mass = mass;
this.fixed = false;
this.diameter = random(1, 10);
this.time = 0;
this.maxTime = random(3, 7);
}
void update(float dt) {
time += dt;
if (!fixed){
//Gravity
force.add(0.0, 200*mass, 0);
//force.div(mass); take this out for simplicity, don't need it for free fall
velocity.add(PVector.mult(force, dt));
position.add(PVector.mult(velocity, dt));
}
//Zero forces
force.mult(0);
}
void render(color c) {
int transparency = floor((time/maxTime)*255);
ellipseMode(CENTER);
fill(blendColor(c, color(255, 255, 255, transparency), BLEND));
noStroke();
ellipse(position.x, position.y, diameter, diameter);
}
boolean shouldDestroy() {
//destroy if off screen
if (position.x > width ||
position.x < 0 ||
position.y > height) {
return true;
}
//destroy if time is up
if (time > maxTime) {
return true;
}
return false;
}
}