Project problems (ParticleSystem / Video)

edited November 2016 in Library Questions

Hello all I am new to processing and have a question with regards to how I would fix my code.

import processing.video.*;

Capture video;

PImage prevFrame;

float threshold = 50;

void setup() {
  size(600,400);
  video = new Capture(this, 640, 480,30);
  video.start();
  ps = new ParticleSystem(new PVector(width/2, 50));
  prevFrame = createImage(video.width, video.height, RGB);
}

void captureEvent(Capture video) {
  prevFrame.copy(video, 0, 0, video.width, video.height, 0, 0, video.width, video.height);
  prevFrame.updatePixels();
  video.read();
}

void draw() {
  background(0);
  image(video, 0, 0);
  ps.addParticle();
  ps.run();
  loadPixels();
  video.loadPixels();
  prevFrame.loadPixels();

  float sumX = 0;
  float sumY = 0;
  int motionCount = 0;

  for (int x = 0; x < video.width; x++ ) {
    for (int y = 0; y < video.height; y++ ) {
      color current = video.pixels[x+y*video.width];

      color previous = prevFrame.pixels[x+y*video.width];

      float r1 = red(current);
      float g1 = green(current);
      float b1 = blue(current);
      float r2 = red(previous); 
      float g2 = green(previous);
      float b2 = blue(previous);

      float diff = dist(r1, g1, b1, r2, g2, b2);

      if (diff > threshold){
        sumX += x;
        sumY += y;
        motionCount ++;
      }
    }
  }

  float avgX = sumX / motionCount;
  float avgY = sumY / motionCount;


  smooth();
  noStroke();
  fill(0);
  ellipse(avgX, avgY, 16, 16);
}

  ParticleSystem ps;


class ParticleSystem {
  ArrayList<Particle> particles;
  PVector origin;

  ParticleSystem(PVector position) {
    origin = position.copy();
    particles = new ArrayList<Particle>();
  }

  void addParticle() {
    particles.add(new Particle(origin));
  }

  void run() {
    for (int i = particles.size()-1; i >= 0; i--) {
      Particle p = particles.get(i);
      p.run();
      if (p.isDead()) {
        particles.remove(i);
      }
    }
  }
}

class Particle {
  PVector position;
  PVector velocity;
  PVector acceleration;
  float lifespan;

  Particle(PVector l) {
    acceleration = new PVector(0, 0.05);
    velocity = new PVector(random(-1, 1), random(-2, 0));
    position = l.copy();
    lifespan = 255.0;
  }

  void run() {
    update();
    display();
  }

  void update() {
    velocity.add(acceleration);
    position.add(velocity);
    lifespan -= 1.0;
  }

  void display() {
    stroke(255, lifespan);
    fill(255, lifespan);
    ellipse(avgX, avgY, 8, 8);
  }

  boolean isDead() {
    if (lifespan < 0.0) {
      return true;
    } else {
      return false;
    }
  }
}

I have two pieces of code with one being able to detect motion and place a dot where it is detected and the other is a particle system and I am trying to place the particle system where movement is detected but I am unsure as to why it is not working, any help is appreciated!

Answers

  • Sorry about that! Should be formatted now.

  • You are trying to use "avgX" and "avgY" inside of your Particle-class.

    ellipse(avgX, avgY, 8, 8);

    It doesn't work, because you only create them inside of draw(). You can instead declare them globally at the top of your sketch, then it should work.

    Add this before setup():

    float avgX, avgY;

    Then change these lines:

      float avgX = sumX / motionCount;
      float avgY = sumY / motionCount;
    

    to this:

      avgX = sumX / motionCount;
      avgY = sumY / motionCount;
    

    Hope it helps.

  • line 26 is adding a new particle

    but it adds it (line 82) using only the origin of the Particle system (set in lines 13 / 77). this is effectively constant so all your particles will start in the same place.

    add an argument to line 81, use that instead of origin in the call to new Particle.

    then you'll need to pass in the position you want in line 26.

  • Thank you all for you're suggestions! I have updated the code but now it shows only one particle in one place rather than generating a lot of them in lots of different places.

  • edited November 2016

    post the new code. or do we have to guess what you've changed?

  • edited November 2016

    Here is the updated code.

       _ _import processing.video.*;
    
        Capture video;
    
        PImage prevFrame;
    
        float threshold = 50;
    
        float avgX, avgY;
    
        void setup() {
          size(600,400);
          video = new Capture(this, 640, 480,30);
          video.start();
          ps = new ParticleSystem(new PVector(width/2, 50));
          prevFrame = createImage(video.width, video.height, RGB);
        }
    
        void captureEvent(Capture video) {
          prevFrame.copy(video, 0, 0, video.width, video.height, 0, 0, video.width, video.height);
          prevFrame.updatePixels();
          video.read();
        }
    
        void draw() {
          background(0);
          image(video, 0, 0);
          ps.addParticle();
          ps.run();
          loadPixels();
          video.loadPixels();
          prevFrame.loadPixels();
    
          float sumX = 0;
          float sumY = 0;
          int motionCount = 0;
    
          for (int x = 0; x < video.width; x++ ) {
            for (int y = 0; y < video.height; y++ ) {
              color current = video.pixels[x+y*video.width];
    
              color previous = prevFrame.pixels[x+y*video.width];
    
              float r1 = red(current);
              float g1 = green(current);
              float b1 = blue(current);
              float r2 = red(previous); 
              float g2 = green(previous);
              float b2 = blue(previous);
    
              float diff = dist(r1, g1, b1, r2, g2, b2);
    
              if (diff > threshold){
                sumX += x;
                sumY += y;
                motionCount ++;
              }
            }
          }
    
          avgX = sumX / motionCount;
          avgY = sumY / motionCount;
    
    
          smooth();
          noStroke();
        }
    
          ParticleSystem ps;
    
    
        class ParticleSystem {
          ArrayList<Particle> particles;
          PVector origin;
    
          ParticleSystem(PVector position) {
            origin = position.copy();
            particles = new ArrayList<Particle>();
          }
    
          void addParticle() {
            particles.add(new Particle(origin));
          }
    
          void run() {
            for (int i = particles.size()-1; i >= 0; i--) {
              Particle p = particles.get(i);
              p.run();
              if (p.isDead()) {
                particles.remove(i);
              }
            }
          }
        }
    
        class Particle {
          PVector position;
          PVector velocity;
          PVector acceleration;
          float lifespan;
    
          Particle(PVector l) {
            acceleration = new PVector(0, 0.05);
            velocity = new PVector(random(-1, 1), random(-2, 0));
            position = l.copy();
            lifespan = 255.0;
          }
    
          void run() {
            update();
            display();
          }
    
          void update() {
            velocity.add(acceleration);
            position.add(velocity);
            lifespan -= 1.0;
          }
    
          void display() {
            stroke(255, lifespan);
            fill(255, lifespan);
            ellipse(avgX, avgY, 8, 8);
          }
    
          boolean isDead() {
            if (lifespan < 0.0) {
              return true;
            } else {
              return false;
            }
          }
        }__
    
  • that contains none of my suggestions

  • Im not sure what you mean koogs I have tried some of the suggestions but im clearly doing something wrong, do you have any examples on what I should be doing?

  • line 63 add something that creates a new particle at average position

    ps.addParticle(new PVector(argX, argY));

    line 81 - 83 change to the following. this allows you to specify a per-particle position (argX, argY from above)

    void addParticle(PVector pos) { particles.add(pos); }

    line 123 - change to use the particle position, not the average position.

    ellipse(position.x, position.y, 8, 8);

    line 28 remove it (line 63 replaces it). you added the particle before calculating where it should spawn.

    the ps.run(); (line 29 ish) should really go under the line that calls addParticle (line 63 ish)

  • you could change isDead to also check if the particle is visible.

  • Thank you for the feedback! Im having an error with the avgX plus avgY and the add part of line 86 any ideas as to why this is so?

    _import processing.video.*;
    
    Capture video;
    
    PImage prevFrame;
    
    float threshold = 50;
    
    float avgX, avgY;
    
    void setup() {
      size(600,400);
      video = new Capture(this, 640, 480,30);
      video.start();
      ps = new ParticleSystem(new PVector(width/2, 50));
      prevFrame = createImage(video.width, video.height, RGB);
      minim = new Minim(this);
      player = minim.loadFile("sandstorm.mp3", 2048);
      player.play();
    }
    
    void captureEvent(Capture video) {
      prevFrame.copy(video, 0, 0, video.width, video.height, 0, 0, video.width, video.height);
      prevFrame.updatePixels();
      video.read();
    }
    
    void draw() {
      background(0);
      image(video, 0, 0);
      loadPixels();
      video.loadPixels();
      prevFrame.loadPixels();
    
      float sumX = 0;
      float sumY = 0;
      int motionCount = 0;
    
      for (int x = 0; x < video.width; x++ ) {
        for (int y = 0; y < video.height; y++ ) {
          color current = video.pixels[x+y*video.width];
    
          color previous = prevFrame.pixels[x+y*video.width];
    
          float r1 = red(current);
          float g1 = green(current);
          float b1 = blue(current);
          float r2 = red(previous); 
          float g2 = green(previous);
          float b2 = blue(previous);
    
          float diff = dist(r1, g1, b1, r2, g2, b2);
    
          if (diff > threshold){
            sumX += x;
            sumY += y;
            motionCount ++;
          }
        }
      }
    
      avgX = sumX / motionCount;
      avgY = sumY / motionCount;
    
      ps.addParticle(new PVector(argX, argY));
      ps.run();
    
    
      smooth();
      noStroke();
    }
    
      ParticleSystem ps;
    
    
    class ParticleSystem {
      ArrayList<Particle> particles;
      PVector origin;
    
      ParticleSystem(PVector position) {
        origin = position.copy();
        particles = new ArrayList<Particle>();
      }
    
      void addParticle(PVector pos) {
        particles.add(pos);
      }
    
      void run() {
        for (int i = particles.size()-1; i >= 0; i--) {
          Particle p = particles.get(i);
          p.run();
          if (p.isDead()) {
            particles.remove(i);
          }
        }
      }
    }
    
    class Particle {
      PVector position;
      PVector velocity;
      PVector acceleration;
      float lifespan;
    
      Particle(PVector l) {
        acceleration = new PVector(0, 0.05);
        velocity = new PVector(random(-1, 1), random(-2, 0));
        position = l.copy();
        lifespan = 255.0;
      }
    
      void run() {
        update();
        display();
      }
    
      void update() {
        velocity.add(acceleration);
        position.add(velocity);
        lifespan -= 1.0;
      }
    
      void display() {
        stroke(255, lifespan);
        fill(255, lifespan);
        ellipse(position.x, position.y, 8, 8);
      }
    
      boolean isDead() {
        if (lifespan < 0.0) {
          return true;
        } else {
          return false;
        }
      }
    }````_
    
  • I have solved the error with avgX and avgY but still have an error with add and I am not sure as to why this is.

  • my bad

    that should've been particles.add(new Particle(pos));

    btw, "still have an error" is no use to anyone. tell us what the error says.

  • (a lot of the time people are answering questions without being able to run the code so can't reproduce the errors. especially true if there are lots of libraries or images or sound files involved, assets we don't necessarily have)

  • Thank you for the reply I have one more error however that is argX and argY do not exist?

    ps.addParticle(new PVector(argX, argY));
      ps.run();
    
  • Note that argX and argY don't exist. You probably meant avgX and avgY.

  • Answer ✓

    this was continued and answered here:

    https://forum.processing.org/two/discussion/19424/particles-appear-in-the-same-place-video-particles

    this wasting of Lord's time is why we don't like duplicate questions...

  • This is precisely the problem. Could you please close this post any admin/moderator?

This discussion has been closed.