# Particles on webcam pixels (and phone cam)

**URL:** <https://discourse.processing.org/t/particles-on-webcam-pixels-and-phone-cam/15868>\
**Category:** Libraries\
**Created:** [November 27, 2019, 11:56am UTC](https://discourse.processing.org/t/particles-on-webcam-pixels-and-phone-cam/15868 "2019-11-27T11:56:09Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![joana](https://avatars.discourse-cdn.com/v4/letter/j/ed655f/32.png) [@joana](https://discourse.processing.org/u/joana)\
**Post date:** [November 27, 2019, 11:56am UTC](https://discourse.processing.org/t/particles-on-webcam-pixels-and-phone-cam/15868/1 "2019-11-27T11:56:09Z")

</div>

Hi there. Based on the frame differencing Processing example, how can I include particle systems to represent the pixels on the webcam? I mean, how can I represent the webcam’s movement through particles?

Here’s an example: [https://www.youtube.com/watch?v=YxFcLAWFwcM&fbclid=IwAR25DN\_FfdtITW7Gj-YnmA5Di9JVX-mUmtqk3SAvdDagbfLZsaKg\_NtFHUQ](https://www.youtube.com/watch?v=YxFcLAWFwcM&fbclid=IwAR25DN_FfdtITW7Gj-YnmA5Di9JVX-mUmtqk3SAvdDagbfLZsaKg_NtFHUQ)

Thanks.

---

<div class="post-metadata">

**Author:** ![noel](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/noel/32/213_2.png) [@noel](https://discourse.processing.org/u/noel)\
**Post date:** [November 27, 2019, 1:54pm UTC](https://discourse.processing.org/t/particles-on-webcam-pixels-and-phone-cam/15868/2 "2019-11-27T13:54:30Z")

</div>

Hi. Nice video. I’m going to work on this also.  
Here is the code.  
[http://www.dayofthenewdan.com/ParticleVideo.zip](http://www.dayofthenewdan.com/ParticleVideo.zip)

---

<div class="post-metadata">

**Author:** ![joana](https://avatars.discourse-cdn.com/v4/letter/j/ed655f/32.png) [@joana](https://discourse.processing.org/u/joana)\
**Post date:** [November 27, 2019, 2:12pm UTC](https://discourse.processing.org/t/particles-on-webcam-pixels-and-phone-cam/15868/3 "2019-11-27T14:12:02Z")

</div>

Hello. Thanks for sharing! I would also appreciate your help 🙂

---

<div class="post-metadata">

**Author:** ![noel](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/noel/32/213_2.png) [@noel](https://discourse.processing.org/u/noel)\
**Post date:** [November 27, 2019, 5:28pm UTC](https://discourse.processing.org/t/particles-on-webcam-pixels-and-phone-cam/15868/4 "2019-11-27T17:28:11Z")

</div>

@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.

```auto
/**
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;
    }
}

```

[![](https://img.youtube.com/vi/15Ham38eUBw/hqdefault.jpg "Particle Video") ](https://www.youtube.com/watch?v=15Ham38eUBw)
