Отслеживание скелета и воспроизведение видео в процессе обработки
Мы использовали следующий код для отслеживания скелета (отслеживания головы) и воспроизведения видео одновременно:
import processing.video.*;
import SimpleOpenNI.*;
import java.util.*;
SimpleOpenNI kinect;
PImage kinectDepth;
int[] userID;
color[] userColor = new color[]{ color(255,0,0), color(0,255,0), color(0,0,255),
color(255,255,0), color(255,0,255), color(0,255,255)};
PVector headPosition = new PVector();
float headSize = 200;
float confidenceLevel = 0.5;
float confidence;
PVector confidenceVector = new PVector();
Movie movie1;
void setup()
{
size(640, 480);
movie1 = new Movie(this, "moon.mP4");
kinect = new SimpleOpenNI(this);
kinect.enableDepth();
kinect.enableUser();
movie1.play();
}
void draw(){
image(movie1, 0, 0, width, height);
kinect.update();
kinectDepth = kinect.depthImage();
image(kinectDepth,0,0);
userID = kinect.getUsers();
for(int i=0;i<userID.length;i++)
{
if(kinect.isTrackingSkeleton(userID[i]))
{
confidence = kinect.getJointPositionSkeleton(userID[i],SimpleOpenNI.SKEL_HEAD,confidenceVector);
if(confidence > confidenceLevel)
{
// change draw color based on hand id#
stroke(userColor[(i)]);
// fill the ellipse with the same color
fill(userColor[(i)]);
// draw the rest of the body
drawSkeleton(userID[i]);
}
}
}
}
/*---------------------------------------------------------------
Draw the skeleton of a tracked user. Input is userID
----------------------------------------------------------------*/
void drawSkeleton(int userId){
kinect.getJointPositionSkeleton(userId, SimpleOpenNI.SKEL_HEAD,headPosition);
kinect.convertRealWorldToProjective(headPosition,headPosition);
ellipse(headPosition.x,headPosition.y,30,30);
}
void onNewUser(SimpleOpenNI curContext, int userId){
println("New User Detected - userId: " + userId);
curContext.startTrackingSkeleton(userId);
}
void onLostUser(SimpleOpenNI curContext, int userId){
println("User Lost - userId: " + userId);
}
void onVisibleUser(SimpleOpenNI curContext, int userId){
} //void onVisibleUser(SimpleOpenNI curContext, int userId)
void movieEvent(Movie m) {
m.read();
}
Следующая ошибка была сгенерирована в файле журнала, когда мы связали выполнение вышеуказанного кода:
Фреймы Java: (J= скомпилированный Java-код, j= интерпретированный, Vv= код VM) J 1472 SimpleOpenNI.SimpleOpenNIJNI.IntVector_size(JLSimpleOpenNI/IntVector;)J (0 байт) @ 0x0000000002ebe695 [0x0000000002ebeNex07171 055N07171.size()J (8 байт) @ 0x0000000002ebe314 [0x0000000002ebe280+0x94] j SimpleOpenNI.SimpleOpenNI.getUsers()[I+15 J 1777 С1 skeleton_track_simpleopen_video.draw()V (1594000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 на АД) 0 (03000000002ebe314)..core.PApplet.handleDraw()V+161 J 1769 C1 processing.awt.PSurfaceAWT$12.callDraw()V (18 байт) @ 0x000000000300009c [0x0000000002ffff80+0x11c] j processing.core.PSurfaceNone$AnimationThread.run() 30 v ~StubRoutines::call_stub
Примечательно, что приведенный выше код работает без каких-либо ошибок при отсутствии воспроизведения видео (библиотека processing.video).
Можно ли помочь нам найти проблему в приведенном выше коде?
1 ответ
Это действительно странное поведение, но чтобы докопаться до сути, может потребоваться скомпилировать библиотеку SimpleOpenNI из исходного кода, отладив ее getUsers()
Метод создает недопустимую ссылку на память.
Это может оказаться непрактичным, если вы просто хотите пройти некоторые тесты и начать работу. Я предлагаю не использовать getUsers()
метод. Вы могли бы, вероятно, уйти с помощью getNumberOfUsers()
:
import processing.video.*;
import SimpleOpenNI.*;
import java.util.*;
SimpleOpenNI kinect;
PImage kinectDepth;
int[] userID;
color[] userColor = new color[]{ color(255,0,0), color(0,255,0), color(0,0,255),
color(255,255,0), color(255,0,255), color(0,255,255)};
PVector headPosition = new PVector();
float headSize = 200;
float confidenceLevel = 0.5;
float confidence;
PVector confidenceVector = new PVector();
Movie movie1;
void setup()
{
size(640, 480);
movie1 = new Movie(this, "moon.mP4");
kinect = new SimpleOpenNI(this,"/Users/George/Downloads/gaf/as/CityWall/oni/test2.oni");
kinect.enableDepth();
kinect.enableUser();
movie1.loop();
}
void draw(){
kinect.update();
kinectDepth = kinect.depthImage();
image(kinectDepth,0,0);
//userID = kinect.getUsers();
for(int i=0;i<kinect.getNumberOfUsers();i++)
{
if(kinect.isTrackingSkeleton(i+1))
{
confidence = kinect.getJointPositionSkeleton(i+1,SimpleOpenNI.SKEL_HEAD,confidenceVector);
if(confidence > confidenceLevel)
{
// change draw color based on hand id#
stroke(userColor[(i)]);
// fill the ellipse with the same color
fill(userColor[(i)]);
// draw the rest of the body
drawSkeleton(i+1);
}
}
}
image(movie1, 0, 0, movie1.width/4, movie1.height/4);
}
/*---------------------------------------------------------------
Draw the skeleton of a tracked user. Input is userID
----------------------------------------------------------------*/
void drawSkeleton(int userId){
kinect.getJointPositionSkeleton(userId, SimpleOpenNI.SKEL_HEAD,headPosition);
kinect.convertRealWorldToProjective(headPosition,headPosition);
ellipse(headPosition.x,headPosition.y,30,30);
}
void onNewUser(SimpleOpenNI curContext, int userId){
println("New User Detected - userId: " + userId);
curContext.startTrackingSkeleton(userId);
}
void onLostUser(SimpleOpenNI curContext, int userId){
println("User Lost - userId: " + userId);
}
void onVisibleUser(SimpleOpenNI curContext, int userId){
} //void onVisibleUser(SimpleOpenNI curContext, int userId)
void movieEvent(Movie m) {
m.read();
}
Не забывайте, что это скажет вам, сколько пользователей отслеживается, а не их идентификаторы. Вместо getNumberOfUsers()
Вы могли бы даже использовать int, скажем 15, максимальное количество пользователей, поддерживаемых OpenNI. Это будет работать, потому что вы всегда проверяете, kinect.isTrackingSkeleton
,