Кинект. Как мне работать с несколькими центрами масс, чтобы они не влияли друг на друга в функциях?

В настоящее время я прохожу курс бакалавриата по изобразительному искусству и недавно начал изучать программирование, читая книгу Грега Боренштейна «Making Things See».

Часть, которую я разрабатываю, — это попытка отслеживать несколько центров масс, когда зрители перемещаются по пространству галереи с помощью Kinect. Я надеялся, что зрители оставят следы на экране, а также, когда они будут приближаться к определенным областям, их близость будет показана линией или чем-то еще. Мне удалось сделать один след, но как только в поле зрения появляется другой человек, их точки внезапно соединяются. «Линия близости» также работает только для текущего пользователя, а не для предыдущих.

Я предполагаю, что мой вопрос действительно сводится к тому, как изолировать каждого нового пользователя, чтобы я мог создавать функции или классы, которые применяются ко всем из них, но не мешают друг другу..?

Вот программа на данный момент...

import processing.opengl.*;
import SimpleOpenNI.*;
import peasy.*;

PeasyCam cam;
SimpleOpenNI kinect;

ArrayList<PVector> trails;

Hotpoint piece;

PVector currentPosition;
PVector previousPosition;

int pieceX = 0;
int pieceY = 0;
int pieceZ = 2000;
int pieceSize = 500;

void setup() {
  size(1280, 680, OPENGL);
  kinect = new SimpleOpenNI(this);
  kinect.enableDepth();
  kinect.enableUser(SimpleOpenNI.SKEL_PROFILE_NONE);
  kinect.setMirror(true);

  trails = new ArrayList();

  piece = new Hotpoint(pieceX, pieceY, pieceZ, pieceSize);

  cam = new PeasyCam(this, 0, 0, 0, 1000);
}

void draw() {
  background(255);
  kinect.update();
  rotateX(radians(180));

  lights();

  stroke(0);
  strokeWeight(3);

  IntVector userList = new IntVector();
  kinect.getUsers(userList);

  piece.draw();

  for (int i=0; i<userList.size(); i++) {
    int userId = userList.get(i);

    PVector positionCenter = new PVector();
    kinect.getCoM(userId, positionCenter);

    trails.add(positionCenter);

    createTrail();

    piece.check(positionCenter);

    if(piece.check(positionCenter) == true) {
      stroke(255, 0, 0);
      line(positionCenter.x, positionCenter.y, positionCenter.z,
           pieceX, pieceY, pieceZ);
      stroke(0);
    }
  }
}

void createTrail() {
  for (int e=1; e < trails.size(); e++) {
    currentPosition = trails.get(e);
    previousPosition = trails.get(e-1);
    if (currentPosition.z < 1) {
      trails.clear();
    } 
    else {
      stroke(0);
      line(previousPosition.x, previousPosition.y, previousPosition.z, 
      currentPosition.x, currentPosition.y, currentPosition.z);
    }
  }
}

А это часть класса Hotpoint...

class Hotpoint {
  PVector center;
  color fillColor;
  color strokeColor;
  int size;
  int pointsIncluded;
  int maxPoints;
  boolean wasJustHit;
  int threshold;


  Hotpoint(float centerX, float centerY, float centerZ, int boxSize) {
    center = new PVector(centerX, centerY, centerZ);
    size = boxSize;
    pointsIncluded = 0;
    maxPoints = 1000;
    threshold = 0;

    strokeColor = color(random(255), random(255), random(255));
    fillColor = 0;
  }

  void setThreshold( int newThreshold ){
    threshold = newThreshold;
  }

  void setMaxPoints( int newMaxPoints ){
    maxPoints = newMaxPoints;
  }

  void setColor(float red, float blue, float green){
    fillColor = strokeColor = color(red, blue, green);
  }

  boolean check(PVector point) {
    boolean result = false;

    if (point.x > center.x - size/2 && point.x < center.x + size/2) {
      if (point.y > center.y - size/2 && point.y < center.y + size/2) {
        if (point.z > center.z - size/2 && point.z < center.z + size/2) {
          result = true;
          pointsIncluded++;
        }
      }
    }

    return result;
  }

  void draw() {
    pushMatrix();
      translate(center.x, center.y, center.z);
      shapeMode(LINES);
      noFill();
      stroke(red(strokeColor), blue(strokeColor), green(strokeColor), 255);
      box(size);
    popMatrix();
  }


  float percentIncluded() {
    return map(pointsIncluded, 0, maxPoints, 0, 1);
  }


  boolean currentlyHit() {
    return (pointsIncluded > threshold);
  }


  boolean isHit() {
    return currentlyHit() && !wasJustHit;
  }

  void clear() {
    wasJustHit = currentlyHit();
    pointsIncluded = 0;
  }
}

Любая помощь будет очень признательна!


РЕДАКТИРОВАТЬ:

Большое спасибо за ваше время и ваш ответ @jesses.co.tt, но у меня возникли проблемы с его пониманием ... Например, цикл по пользовательскому списку - это не то же самое, что массив пользователей? Я беспокоюсь, что спрашиваю больше, чем одну вещь за раз, поэтому я разбил ее, чтобы попытаться понять, во-первых, рисование нескольких троп без связанных между собой людей.

import processing.opengl.*;
import SimpleOpenNI.*;
import peasy.*;

SimpleOpenNI kinect;
PeasyCam cam;

ArrayList<PVector> trails1;
ArrayList<PVector> trails2;

PVector currentPosition;
PVector previousPosition;

void setup() {
  size(1280, 800, OPENGL);

  kinect = new SimpleOpenNI(this);
  kinect.enableDepth();
  kinect.enableUser(SimpleOpenNI.SKEL_PROFILE_NONE);
  kinect.setMirror(true);

  trails1 = new ArrayList();
  trails2 = new ArrayList();

  cam = new PeasyCam(this, 0, 0, 0, 1000);
}

void draw() {
  kinect.update();
  rotateX(radians(180));
  background(255);

  IntVector userList = new IntVector();
  kinect.getUsers(userList);

  //println(userList);

  for (int i=0; i<userList.size(); i++) {
    int userId = userList.get(i);
    //println(userId);
    PVector positionCenter = new PVector();
    kinect.getCoM(userId, positionCenter);

    stroke(0);
    strokeWeight(10);
    point(positionCenter.x, positionCenter.y, positionCenter.z);

    if (userId == 1) {

      trails1.add(positionCenter);
      createTrail1();
    } 
    else if (userId == 2) {
      trails2.add(positionCenter);
      createTrail2();
    }
  }
}

void createTrail1() {
  for (int e=1; e < trails1.size(); e++) {
    currentPosition = trails1.get(e);
    previousPosition = trails1.get(e-1);
    if (currentPosition.z < 1) { // [possibly x or y or all?]
      trails1.clear();
    } 
    else {
      // if (currentPosition.x != 0 || previousPosition.x != 0) { // [not working]
      stroke(0);
      line(previousPosition.x, previousPosition.y, previousPosition.z, 
      currentPosition.x, currentPosition.y, currentPosition.z);
      //trails.clear();
    }
  }
}

void createTrail2() {
  for (int e=1; e < trails2.size(); e++) {
    currentPosition = trails2.get(e);
    previousPosition = trails2.get(e-1);
    if (currentPosition.z < 1) { // [possibly x or y or all?]
      trails2.clear();
    } 
    else {
      // if (currentPosition.x != 0 || previousPosition.x != 0) { // [not working]
      stroke(0);
      line(previousPosition.x, previousPosition.y, previousPosition.z, 
      currentPosition.x, currentPosition.y, currentPosition.z);
      //trails.clear();
    }
  }
}

Итак, это сработало бы для двух человек, и я мог бы написать ужасно длинную программу для работы с большим конечным числом людей, но мне действительно хотелось бы, чтобы она была динамической... Где это 'if (userId = = 1) {', я бы хотел, чтобы это работало для всех, тогда в части следов должен быть новый массив следов, чтобы каждый раз, когда в поле зрения появлялся новый человек, я использовал "void onNewUser (int userId) {' или что-то в этом роде..?


person basicallyright    schedule 23.04.2013    source источник
comment
К сожалению, я забыл включить класс Hotpoint, так что теперь он был отредактирован!   -  person basicallyright    schedule 24.04.2013


Ответы (1)


Насколько я могу судить, вам нужно составить изменяемый список пользователей, который уже предоставлен вам SimpleOpenNI, и создать новый экземпляр вашего класса HotPoint для каждого нового пользователя, которого вы найдете (или удалить его для каждого пользователя, который исчезает). )...

Вы почти у цели, так как правильно перебираете список известных пользователей...

Вам нужно добавить ArrayList HotPoints, размер которого изменяется в соответствии с количеством найденных пользователей... затем создайте новый экземпляр точки, когда будет найден новый пользователь. Как у вас сейчас, у вас есть только один экземпляр, поэтому, если есть два пользователя, он соединит их - что вы и видите.

Обязательно удаляйте элементы из ArrayList по мере необходимости!

Вы очень близки... ;-)

So...

// Global Variables
ArrayList users;

Затем в вашем цикле for над пользователями...

// Add a new HotPoint if we have more users than Points
if(i > users.size()) {
  users.add(new HotPoint(...));
}
// Delete From ArrayList if we have too many... 
else if(users.size() > userList.size()) {
  users.remove(...);
} 

// Cast and call methods
HotPoint piece = (HotPoint) users.get(i);
piece.check(positionCenter);
piece.draw();
etc...
person jesses.co.tt    schedule 24.04.2013
comment
Большое спасибо за ваш ответ @jesses.co.tt Это определенно обнадеживает, хотя мне все еще трудно понять все это. Я отредактировал вопрос, чтобы, надеюсь, еще немного разобраться в своих проблемах... Было бы здорово, если бы вы могли помочь дальше! - person basicallyright; 04.05.2013