⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 silhouette.pde

📁 通过隐式马尔可夫方法(HMM算法)提取视频背景
💻 PDE
字号:
/**
 * Silhouette class
 * Manages silhouette data, draws it and tests collisions
 * 
 *
 * Jorge Cardoso http://jorgecardoso.eu
 * January 2008
 */

public class Silhouette {

  // The vectorized and normalized ([0,1]) silhouette. [n][0] - x coord, [n][1] - y coord 
  float silhouette[][];

  // computed on testing for 'insideness'. represent the index of closest point to the
  // one last tested tested. See inside(x, y);
  private float closestX, closestY;
  // the normal of the closest segment to the last tested point
  private float normalX, normalY;

  // the default dimension of the  silhouette
  // this is just used to scale when drawing
  private int width = 0, height = 0;

  // the bounding box of the silhouette in the image.
  private float bbx, bby, bbwidth, bbheight;

  // the area of the silhouette
  private float area;

  // the center of mass of the silhouette
  private float centerOfMassX, centerOfMassY;


  public Silhouette(float [][] s) {
    silhouette = s;

    if (s == null) {
      println("Null silhouette polygons");
      return;
    }
    
    // calculate the bounding box
    calculateBB();
  }

  public void setSize(int width, int height) {
    this.width = width;
    this.height = height;
    
    // reculculate the area, center of mass and normals
    area = (float)calculateArea(this.silhouette)*this.width*this.height;
    Point2D.Double com = calculateCenterOfMass(this.silhouette);
    centerOfMassX = (float)com.getX();
    centerOfMassY = (float)com.getY();

  }

  // draw the silhouette with a texture image in a particular coord and scaled according to the passed
  // width and height
  public void draw(PImage text, int x, int y, int width, int height) {
    float[][] s = silhouette;
    // strokeWeight(3);
    fill(255);
    beginShape(POLYGON);
    texture(text);
    for (int i = 0; i < s.length; i++) {
      vertex(s[i][0]*width+x, s[i][1]*height+y, s[i][0]*text.width, s[i][1]*text.height);
    }
    vertex(s[0][0]*width+x, s[0][1]*height+y, s[0][0]*text.width, s[0][1]*text.height);
    endShape();
  }

  // draw the silhouette with a texture image
  // in the default coords (0, 0) and with the default dimension
  public void draw(PImage text) {
    draw(text, 0, 0, this.width, this.height);
  }

  // draw the silhouette with a texture image
  // in a particular coord and with the default dimension
  public void draw(PImage text, int x, int y) {
    draw(text, x, y, this.width, this.height);
  }

  // draws the silhoutte in a particular coord and scaled according to the passed width and height
  public void draw(int x, int y, int width, int height) {
    if (width == 0 || height == 0) {
      println("Width or height equal to zero!!");
      println("Call setSize()");
    }
    float[][] s = silhouette;
    //strokeWeight(3);
    for (int i = 0; i < s.length; i++) {
      if (i > 0 ) { 
        line((int)(s[i-1][0]*width)+x, (int)(s[i-1][1]*height)+y, (int)(s[i][0]*width)+x, (int)(s[i][1]*height)+y);
      }
    }
    line((int)(s[s.length-1][0]*width)+x, (int)(s[s.length-1][1]*height)+y, (int)(s[0][0]*width)+x, (int)(s[0][1]*height)+y);
  }

  // draws the silhoutte in a particular coord, using the default size
  public void draw(int x, int y) {
    draw(x, y,  this.width,  this.height);
  }

  // draws the silhoutte in the default coord, using the default size
  public void draw() {
    draw(0, 0,  this.width,  this.height);
  }

  // returns true if the specified point is inside this silhouette's bounding box
  public boolean insideBoundingBox(float x, float y) {
    if (x < bbx*this.width || x > (bbx+bbwidth)*this.width || y < bby*this.height || y > (bby+bbheight)*this.height) {
      return false;
    }
    return true;
  }

  // checks if a point is inside the silhouette polygon
  public boolean inside(float x, float y) {
    return insidePolygon(x, y, silhouette, this.width, this.height);
  }


  // Code is borrowed from this http://processing.org/discourse/yabb_beta/YaBB.cgi?board=Programs;action=display;num=118917882
  // thread. Thanks to <a href="http://www.robotacid.com/">st33d</a> for the code. 
  // this also calculates the closest point on the silhouette to the one being tested
  public boolean insidePolygon(float x,float y, float p[][], int width, int height) {

    int i, j, c = 0;

    x = x/width;
    y = y/height;

    float min = 1000000;
    int minIndex = 0;
    float d;
    float inter[] = new float[2]; // intersection
    float minInter[] = new float[2]; //
    for (i = 0, j = p.length-1; i < p.length; j = i++) {
      if ((((p[i][1] <= y) && (y < p[j][1])) ||
        ((p[j][1] <= y) && (y < p[i][1]))) &&
        (x < (p[j][0] - p[i][0]) * (y - p[i][1]) / (p[j][1] - p[i][1]) + p[i][0])) {
        c = (c+1)%2;
      }
      // calculate the intersection with the segment
      inter = intersection(x, y, p[i][0], p[i][1], p[(i+1)%p.length][0], p[(i+1)%p.length][1]);
      if ( inter != null && (d = dist(inter[0], inter[1], x, y)) < min ) {
        min = d;
        minIndex = i;
        minInter[0]=inter[0];
        minInter[1] = inter[1];
      }
    }

    closestX = minInter[0]*this.width;
    closestY = minInter[1]*this.height;
    Point2D.Double n = normal((int)(p[minIndex][0]*this.width), (int)(p[minIndex][1]*this.height), 
    (int)(p[(minIndex+1)%p.length][0]*this.width), (int)(p[(minIndex+1)%p.length][1]*this.height));

    normalX =(float) (n.getX());
    normalY  =(float) (n.getY());
    //closest = minIndex;
    return c==1;
  } 

  public float distanceToSilhouette(float x, float y) {
    float p[][] = silhouette;

    float min = 1000000;
    int minIndex = 0;
    float d;
    float inter[] = new float[2]; // intersection
    float minInter[] = new float[2]; //
    for (int i = 0; i < p.length; i++) {

      // calculate the intersection with the segment
      inter = intersection(x, y, p[i][0]*width, p[i][1]*height, p[(i+1)%p.length][0]*width, p[(i+1)%p.length][1]*height);
      if ( inter != null && (d = dist(inter[0], inter[1], x, y)) < min ) {
        min = d;
        minIndex = i;
        minInter[0]=inter[0];
        minInter[1] = inter[1];
      }
    }

    closestX = minInter[0];
    closestY = minInter[1];
    Point2D.Double n = normal((int)(p[minIndex][0]*this.width), (int)(p[minIndex][1]*this.height), 
    (int)(p[(minIndex+1)%p.length][0]*this.width), (int)(p[(minIndex+1)%p.length][1]*this.height));

    normalX =(float) (n.getX());
    normalY  =(float) (n.getY());
    //closest = minIndex;
    return min;

  }

  public int bbX() {
    return (int)(bbx*this.width);
  }

  public int bbY() {
    return   (int)(bby*this.height);
  }

  public int bbWidth() {
    return   (int)(bbwidth*this.width);
  }
  public int bbHeight() {
    return   (int)(bbheight*this.height);
  } 
  
  public float area() {
    return area; 
  }

  public float getCenterOfMassX() {
    return centerOfMassX*this.width;
  }

  public float getCenterOfMassY() {
    return centerOfMassY*this.height;
  }
  
  public float getNormalX() {
    return normalX;
  }
  public float getNormalY() {
    return normalY;
  }

  public float getClosestX() {
    return closestX;
  }
  public float getClosestY() {
    return closestY;
  }
  // 
  private void calculateBB() {
    float minx = 1000000, miny = 100000, maxx = -1000000, maxy = -100000;
    float s[][] = silhouette;
    for (int i = 0; i < s.length; i++) {
      if (s[i][0] < minx) {
        minx = s[i][0];
      }
      if (s[i][0] > maxx) {
        maxx = s[i][0];
      }     
      if (s[i][1] < miny) {
        miny = s[i][1];
      }
      if (s[i][1] > maxy) {
        maxy = s[i][1];
      }  
    }

    bbx = minx;
    bby = miny;
    bbwidth = (maxx-minx);
    bbheight = (maxy-miny);
  }

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -