Loading...
Logo
Processing Forum

Blend particles?

in Contributed Library Questions  •  4 months ago  
Is there a way to use blend() on particles? Or is there a way to make a PImage out of a particlesystem so blend() can be applied to particles? I want all my white particles to blend into a video as a simple way to mask the video.

I now used a particlesystem as a mask for a video using PGraphics, but it is running very slow, partly because I have to draw rectangles instead of points.

My goal is to use particles as a way to mask a video. I am using the kinect to draw the particles, so your silhouette is made out of these particles. Here's how it looks like (my head, made out of particles is masking a video):



If you have any better suggestions, they are also welcome!

Replies(5)

Re: Blend particles?

4 months ago
in theory, sure!

in practice it depends on the implementation of your particle class.

if you have written your own, then it probably has a display function where you can either use alpha() if you're using an ellipse as your particle, or make a PImage part of the class use blend() .  if you did make your own particle class, post the code and people on the forums can take a look for you.

if you are using a pre-made class in a library such as box2d, then you might want to ask on the box2d forums.  i don't know anything about the internals but i suspect it's not out of the realm of possibility.

Re: Blend particles?

4 months ago
Thanks for your answer!

I think I have to make a PImage out of a PVector. (sort of what is done over here: http://www.openprocessing.org/sketch/30862)

I can blend rgbImg (PImage) from the kinect camera, not map3d (PVector). Simply said I'd like map3d (PVector) to become part of vectorImg (PImage), which I can then hopefully blend by using blend().

Here is the code (I am building on this sketch http://www.openprocessing.org/sketch/60316):

Copy code
  1. import SimpleOpenNI.*;
    import controlP5.*;
    import toxi.geom.*;
    import java.util.Iterator;
    import jmcvideo.*;

    public int     resolution = 3;
    public int     pixelsResolution;
    public int     pixelSize = resolution;
    public boolean drawPixels = false;
    public boolean follow =  false;
    public boolean sandEffect = false;


    SimpleOpenNI context;

    int cap_width = 1024;
    int cap_height = 768;

    float zoomF = 0.35;
    float rotX  = PI;
    float rotY  = 0;

    PImage maskImage;
    PGraphics graphicalMask;
    PImage backgroundImg;
    PImage rgbImg;
    PVector[] map3D;
    PImage vectorImg;


    JMCMovie backMovie;
    URL url;

    Particles      par;

    void setup(){
      //size(1440, 900,P3D);
      size(cap_width,cap_height,P3D);
      frameRate(300);
      perspective(radians(25),float(width)/float(height),10.0,150000.0);
     
      backgroundImg = loadImage("backgrounddust_img1024rand.jpg");
      backMovie = movieFromDataPath("moderntimes.mov");
      backMovie.loop();
      graphicalMask = createGraphics(cap_width, cap_height, JAVA2D);
      vectorImg = createImage(cap_width,cap_height, ARGB);
                           
      context = new SimpleOpenNI(this);
      context.setMirror(true);
      context.enableDepth(); 
      context.enableRGB();
      context.alternativeViewPointDepthToImage();

      context.update();

      calculateLimits(context.depthMap(),context.depthMapRealWorld());
     
      controlPanel();
    }

    void draw(){
      context.update();
      int[] depthMap = context.depthMap();
      PVector[] realWorldMap = context.depthMapRealWorld();
      PImage rgbImage = context.rgbImage();

      int[] resDepth = resizeDepth(depthMap,resolution);
      PVector[]resMap3D = resizeMap3D(realWorldMap,resolution);
      PImage resRGB = resizeRGB(rgbImage,resolution);
      boolean[] constrainedImg = constrainImg(resDepth,resMap3D,xmin,xmax,ymin,ymax,zmin,zmax);
      int resXsize = context.depthWidth()/resolution;
      int resYsize = context.depthHeight()/resolution;
     
      background(backgroundImg);
      //background(0);
      translate(width/2,height/2,50);
      rotateX(rotX);
      rotateY(rotY);
      scale(zoomF);
     
     
      if(drawPixels){
        par = new Particles(resMap3D,resRGB,constrainedImg);
        //connectedLine = new ConnectedLines(resMap3D,constrainedImg,resXsize,resYsize);
        if(realColor){
          par.paint(pixelSize);
          //connectedLine.paint(color(200));
        }
        else{
                         
          par.paint(pixelSize,color(200));
     
          //connectedLine.paint(color(200));
        }

        if(follow){
          particlesList.add(par);
          if(sandEffect){
            for(int i = 0; i < particlesList.size()-1; i++){
              par = (Particles) particlesList.get(i);
             
                   graphicalMask.beginDraw();
                   graphicalMask.background(0);
                     
              par.paint(pixelSize,color(200,0));
              par.update(ymin);
             
                   graphicalMask.endDraw();
                   maskImage = backMovie.get();
                   maskImage.resize(1024,768);
                   maskImage.mask(graphicalMask);
                   image(maskImage,-480,-360);
                 
            }
            if(particlesList.size() > 15){
              particlesList.remove(0);
            }
          }
          else{
            if(particlesList.size() > 30){
              Particles par1 = (Particles) particlesList.get(15);
              Particles par2 = (Particles) particlesList.get(0);
              if(realColor){
                par1.paint(pixelSize);
                par2.paint(pixelSize);
              }
              else{
                par1.paint(pixelSize,color(200));
                par2.paint(pixelSize,color(200));
              }
              particlesList.remove(0);
            }
          }
        }
        else{
          particlesList.clear();
        }
      }
  2. //Particles class
    class Particles{


      boolean[] consImg;
      PVector[] vel;
      int nPar;

      Particles(PVector[] tempMap3D, PImage tempRGBimg, boolean[] tempConsImg){
        map3D = tempMap3D;
        rgbImg = tempRGBimg;
        consImg = tempConsImg;
        nPar = map3D.length;
        vel = new PVector[nPar];
        for(int i = 0; i < nPar; i++){
          vel[i] = new PVector(0,0,0);
        }
      }
     
      void paint(int pSize){
        strokeWeight(pSize);

        for(int i = 0; i < nPar; i++){
          if(consImg[i]){
            PVector p = map3D[i];
            stroke(rgbImg.pixels[i]);
            point(p.x,p.y,p.z);
            
          } 
        }
      }
     
      void paint(int pSize, color col){
        strokeWeight(pSize);
        stroke(col);
       
        for(int i = 0; i < nPar; i++){
          if(consImg[i]){
            PVector p = map3D[i];
         
             graphicalMask.noStroke();     
             graphicalMask.rect(p.x,p.y,2,2);
           
          } 
        }
      }
     
      void update(float yMin){
        PVector g = new PVector(0,-0.1,0);
       
        for(int i = 0; i < nPar; i++){
          if(consImg[i]){
            if((map3D[i].y + vel[i].y) > yMin){
              map3D[i].add(vel[i]);
              vel[i].add(g);
            }
            else{
              map3D[i].y = yMin;
            }
          }
        }
      }
     
    }
  3. //Kinect utilities
    void calculateLimits(int[] depthImg, PVector[] map3D){
      float xMin, xMax, yMin, yMax, zMin, zMax;
      xMin = yMin = zMin = 10000;
      xMax = yMax = zMax = -10000;
     
      for(int i = 0; i < depthImg.length; i++){
        if(depthImg[i] > 0){
          PVector p = map3D[i];
          if(p.x < xMin){
            xMin = p.x;
          }
          if(p.x > xMax){
            xMax = p.x;
          }
          if(p.y < yMin){
            yMin = p.y;
          }
          if(p.y > yMax){
            yMax = p.y;
          }
          if(p.z < zMin){
            zMin = p.z;
          }
          if(p.z > zMax){
            zMax = p.z;
          }
        }
      }
      xmin = xMin - 0.1*(xMax - xMin);
      xmax = xMax + 0.1*(xMax - xMin);
      ymin = yMin - 0.1*(yMax - yMin);
      ymax = yMax + 0.1*(yMax - yMin);
      zmin = zMin - 0.5*(zMax - zMin);
      zmax = zMax + 0.1*(zMax - zMin);


    int[] resizeDepth(int[] depthImg, int n){
      int xSizeOrig = context.depthWidth();
      int ySizeOrig = context.depthHeight();
      int xSize = xSizeOrig/n;
      int ySize = ySizeOrig/n;
      int[] resDepthImg = new int[xSize*ySize];

      for(int y = 0; y < ySize; y++){
        for(int x = 0; x < xSize; x++){
          resDepthImg[x + y*xSize] = depthImg[x*n + y*n*xSizeOrig];
        }
      }
      return resDepthImg;
    }

    PVector[] resizeMap3D(PVector[] map3D, int n){
      int xSizeOrig = context.depthWidth();
      int ySizeOrig = context.depthHeight();
      int xSize = xSizeOrig/n;
      int ySize = ySizeOrig/n;
      PVector[] resMap3D = new PVector[xSize*ySize];

      for(int y = 0; y < ySize; y++){
        for(int x = 0; x < xSize; x++){
          resMap3D[x + y*xSize] = map3D[x*n + y*n*xSizeOrig].get();
        }
      }
      return resMap3D;
    }

    PImage resizeRGB(PImage rgbImg, int n){
      int xSizeOrig = context.depthWidth();
      int ySizeOrig = context.depthHeight();
      int xSize = xSizeOrig/n;
      int ySize = ySizeOrig/n;
      PImage resRGB = createImage(xSize,ySize,RGB);
     
      for(int y = 0; y < ySize; y++){
        for(int x = 0; x < xSize; x++){
          resRGB.pixels[x + y*xSize] = rgbImg.pixels[x*n + y*n*xSizeOrig];
        }
      }
      return resRGB;
    }

    boolean[] constrainImg(int[] depthImg, PVector[] map3D, float xMin, float xMax, float yMin, float yMax, float zMin, float zMax){
      boolean[] consImg = new boolean[depthImg.length];

      for(int i = 0; i < consImg.length; i++){
        PVector p = map3D[i];
        consImg[i] = (depthImg[i] > 0) && (p.x > xMin) && (p.x < xMax) && (p.y > yMin) && (p.y < yMax) && (p.z > zMin) && (p.z < zMax);
      }
      return consImg;


Re: Blend particles?

4 months ago
Admittedly, i'm stepping a bit out outside my capabilities but no one else is responding so maybe this will help you see it from a different perspective.  not being able to run the program, here's what I see.

Keep in mind that you cannot make a PImage out of a PVector, and likewise, you cannot blend a PVector.  A PVector stores an x, y location.  What you can blend is something (point, image, rect) that is placed at a location PVector.x, PVector.y (and PVector.z).

What's happening with map3D is that it is being used to create a PVector for the location for a point in the first paint function, and the location of a rect in the second.  I think what you may need to do is replace the PGraphics mask with a PImage mask.  Then you might be able to re-use the paint function above only this time add alpha before the point().  You'll still need two paint functions but you can call one paintRGBImg and the other paintMaskImg.

I hope I haven't led you down too much of a wrong path.  I can say with 100% assurance that the second paragraph is true so perhaps reframing your problem will be helpful.

Re: Blend particles?

4 months ago
Thanks again for your reply and thinking with me.

You're indeed right about the second paragraph.

But no worries, I already found another way to solve this, by simply detecting all of the white pixels on the display window. I opened another topic for this issue as well ( http://forum.processing.org/topic/read-all-white-pixels )
A PImage detects all of the white pixels that are returned by the PVector. The PImage then blends all of the white pixels with the video. It's indeed working much faster than masking the video with particle rectangles.

Re: Blend particles?

4 months ago
nice!  glad i could write a paragraph with things that are true.