I am trying to use an SVM in Android using OpenCV's Android SDK. Everything seems to work correctly besides the predict() function.
I get the following error:
svm CvException error: (-215) samples.cols == var_count && samples.type() == CV_32F in function virtual float cv::ml::SVMImpl::predict(cv::InputArray, cv::OutputArray, int) const ]
I am rather certain that the dimensions and types are correct, but I have a feeling I am overlooking something simple. Below is the description of my code with the relevant code.
I have 60 training examples with 150 features each. All examples and labels are in a 2D float array of dimension 60x151 called dataset_2Darr. The right-most column has the labels stored as -1, 0, +1 for the three classes.
I first place the 60x150 sub-matrix in the Mat object X.
Then, I place the labels in the 60x1 Mat object Y.
X is float - CV_ 32FC1
Y is int - CV_32SC1
The relevant code is executed in 3 parts of the overall program. Here are the three parts:
Part 1: Global Variables in top of MainActivity.java:
static int M = 60; // Rows - examples
static int N = 150; // Cols - features
public static Mat X; // Data
public static Mat Y; // Labels
// Instantiate SVM object globally
static SVM classifier = SVM.create();
Part 2: Inside OnCreate():
// SVM Stuff:
classifier.setKernel(SVM.LINEAR);
classifier.setType(SVM.C_SVC);
classifier.setGamma(0.5);
classifier.setNu(0.5);
classifier.setC(1);
//classifier.setTermCriteria(criteria);
// Dataset stuff:
Y = new Mat(new Size(1,M),CvType.CV_32SC1); // Integer {-1, 0, +1}
int Y_rows = Y.rows(); // 60
int Y_cols = Y.cols(); // 1
X = new Mat(new Size(N,M),CvType.CV_32FC1); // Float
int X_rows = X.rows(); // 60
int X_cols = X.cols(); // 150
Part 3: Inside method that executes code:
for (int i=0; i < 60; i++) {
for(int j=0; j < 150; j++) {
X.put(i, j, dataset_2Darr[i][j]); // Copy 2D array into mat object
}
}
// Iterate down rows of right-most column
for (int i = 0; i < 60; ++i)
Y.put(i,0, (int)dataset_2Darr[i][150]); // Copy right most column into label array
// Train the model using X and Y
classifier.train(X, Ml.ROW_SAMPLE, Y);
// Create 1x150 feature vector to test:
Mat x = new Mat(new Size(150, 1),CvType.CV_32FC1); // Float
int x_rows = x.rows(); // 1
int x_cols = x.cols(); // 150
// Place dummy values inside matrix x
for (int i = 0; i < 150; i++) {
x.put(0, i, 0.2f);
}
//Mat outMat = new Mat();
//float response = classifier.predict(x, outMat, 0);
float prediction = classifier.predict(x);
I met the same problem recently. The shape and type of test data are fine, but somehow the SVM model cannot work with the test data.
The solution is that you need to make sure the dimension of test data is the same as the training data.
Note that the dimension of [1,2,3] is 1, and the dimension of [[1,2,3]] is 2.
Related
I am trying to create a color tracking bird flock, using live video from my webcam. I was instructed to use a constructor to create an array of .gifs that could work independently and follow a specific color around the video.
I did some research and this is as far as I got. Now I am getting an error that I don't really understand. For a very early dummy example of the intentions i have with the code, please see this .gif: Flock of birds
import processing.video.*;
import gifAnimation.*;
video = new Movie(); /// This is the line that gives me the error
// class
Birdy [] arrayOfBirds;
int numberOfBirds = 10;
class Birdy
{
//variables
int numberOfBeaks;
String birdName;
color birdColor;
PVector location;
// constructor, allows you to make new Birds in the rest of the code
// A constructor is part of the class
Birdy (int nob, String bname, color bColor, PVector loc) {
numberOfBeaks = nob;
birdName = bname;
birdColor = bColor;
location = loc;
}
//The bird appears
void showBird()
{
fill(birdColor);
textSize(24);
text(birdName, location.x, location.y);
ellipse(location.x, location.y, 20, 20);
}
}
void setup() {
size(640, 480);
//fill the array Of Birds with new Birds
arrayOfBirds = new Birdy[numberOfBirds];
//to make 10 birds and put them in the array
for (int i = 0; i < numberOfBirds; i++)
{
// each new bird needs its own set of parameters but will do this when i figure out how to work with this one first!
arrayOfBirds[i]= new Birdy(2, "Tweety "+i, color(255-(i*25), i*25, 255), new PVector(i*40, i*40));
}
}
void draw(int x, int y) {
if (video.available()) {
video.read();
image(video, 0, 0, width, height); // Draw the webcam video onto the screen
int colorX = 0; // X-coordinate of the closest in color video pixel
int colorY = 0; // Y-coordinate of the closest in color video pixel
float closestColor = 500; //we set this to be abritrarily large, once program runs, the first pixel it scans will be set to this value
// Search for the closest in color pixel: For each row of pixels in the video image and
// for each pixel in the yth row, compute each pixel's index in the video
background(0);
//show that first bird we called Tweety by calling the showBird() function on Tweety
Tweety.showBird();
//show all the birds in the array by calling the showBird() method on each object in the array
for(int i = 0; i < arrayOfBirds.length; i++){
arrayOfBirds[i].location = new PVector(x,y);
arrayOfBirds[i].showBird();
}
}
setup();
Gif loopingGif;
Capture video;
size(640, 480); // Change size to 320 x 240 if too slow at 640 x 480 // Uses the default video input ---- but i dont think it works
video = new Capture(this, width, height, 30);
video.start();
noStroke();
smooth();
frameRate(10);
loopingGif = new Gif(this, "circle.gif");
String [] animas = {};
video.loadPixels();
int index = 0;
for (int y = 0; y < video.height; y++) {
for (int x = 0; x < video.width; x++) {
// Get the color stored in the pixel
color pixelValue = video.pixels[index];
// Determine the color of the pixel
float colorProximity = abs(red(pixelValue)-27)+abs(green(pixelValue)-162)+abs(blue(pixelValue)-181); //select pixel
// If that value is closer in color value than any previous, then store the
// color proximity of that pixel, as well as its (x,y) location
if (colorProximity < closestColor) {
closestColor = colorProximity;
closestColor=closestColor-10; //Once it "locks" on to an object of color, it wont let go unless something a good bit better (closer in color) comes along
colorY = y;
colorX = x;
}
index++;
}
draw(x,y);
}
image (loopingGif, colorX, colorY);
loopingGif.play();
}here
You need to declare your variable by giving it a type:
Movie video = new Movie();
You've got some other weird things going on here. Why are you specifically calling the setup() function? Processing does that for you automatically. You've also got a bunch of code outside of a function at the bottom of your sketch. Maybe you meant to put that code inside the setup() function?
If you're still getting errors, edit your question to include their exact full text.
I've been working on a Java program that reads an image, subdivides it into a definable number of rectangular tiles, then swaps the pixels of each tile with those of another tile, and then puts them back together and renders the image.
An explanation of the idea: http://i.imgur.com/OPefpjf.png
I've been using the BufferedImage class, so my idea was to first read all width * height pixels from its data buffer and save them to an array.
Then, according to the tile height and width, copy the entire pixel information of each tile to small arrays, shuffle those, and then write back the data contained in these arrays to their position in the data buffer. It should then be enough to create a new BufferedImage with the original color and sample models as well as the updated data buffer.
However, I got ominous errors when creating a new WriteableRaster from the updated data buffer, and the number of pixels didn't match up (I had suddenly gotten 24 instead of originally 8, and so forth), so I figured there is something wrong with the way I address the pixel information.
( Reference pages for BufferedImage and WriteableRaster )
I used the following loop to iterate through the 1D data buffer:
// maximum iteration values
int numRows = height/tileHeight;
int numCols = width/tileWidth;
// cut picture into tiles
// for each column of the image matrix
// addressing columns (1D)
for ( int column = 0; column < numCols; column++ )
{
// for each row of the matrix
// addressing cells (2D)
for ( int row = 0; row < numRows; row++ )
{
byte[] pixels = new byte[(tileWidth+1) * (tileHeight+1)];
int celloffset = (column + (width * row)); // find cell base address
// for each row inside the cell
// adressing column inside a tile (3D)
for ( int colpixel = 0; colpixel < tileWidth; colpixel++ )
{
// for each column inside the tile -> each pixel of the cell
for ( int rowpixel = 0; rowpixel < tileHeight; rowpixel++ )
{
// address of pixel in original image buffer array allPixels[]
int origpos = celloffset + ((rowpixel * tileWidth) + colpixel);
// translated address of pixel in local pixels[] array of current tile
int transpos = colpixel + (rowpixel * tileWidth);
// source, start, dest, offset, length
pixels[transpos] = allPixels[origpos];
}
}
}
}
Is there something wrong with this code? Or is there perhaps a much easier way to do this that I haven't thought of yet?
The code below edits the image in place. So no need to create new objects, which should simplify. If you need to keep the original, just copy it entirely first. Also, no need to save to separate arrays.
Since you said "shuffle" I assume you want to swap the tiles randomly. I made a function for that, and if you just call it many times you will end up with tiles swapped randomly. If you want a pattern or some other rule of how they are swapped, just call the other function directly with your chosen tiles.
I haven't used BufferedImage before, but looking at the documentation,
http://docs.oracle.com/javase/7/docs/api/java/awt/image/BufferedImage.html
and this post,
Edit pixel values
It seems that an easy way is to use the methods getRGB and setRGB
int getRGB(int x, int y)
Returns an integer pixel in the default RGB color model
(TYPE_INT_ARGB) and default sRGB colorspace.
void setRGB(int x, int y, int rgb)
Sets a pixel in this BufferedImage to the specified RGB value.
I would try something like the following: (untested code)
Using random http://docs.oracle.com/javase/7/docs/api/java/util/Random.html
int numRows = height/tileHeight;
int numCols = width/tileWidth;
void swapTwoRandomTiles (BufferedImage b) {
//choose x and y coordinates randomly for the tiles
int xt1 = random.nextInt (numCols);
int yt1 = random.nextInt (numRows);
int xt2 = random.nextInt (numCols);
int yt2 = random.nextInt (numRows);
swapTiles (b,xt1,yt1,xt2,yt2);
}
void swapTiles(BufferedImage b, int xt1, int yt1, int xt2, int yt2) {
int tempPixel = 0;
for (int x=0; x<tileWidth; x++) {
for (int y=0; y<tileHeight; y++) {
//save the pixel value to temp
tempPixel = b.getRGB(x + xt1*tileWidth, y + yt1*tileHeight);
//write over the part of the image that we just saved, getting data from the other tile
b.setRGB ( x + xt1*tileWidth, y + yt1*tileHeight, b.getRGB ( x+xt2*tileWidth, y+yt2*tileHeight));
//write from temp back to the other tile
b.setRGB ( x + xt2*tileWidth, y + yt2*tileHeight, tempPixel);
}
}
}
I have experimented and I can't find a way to parse an array of Integers and a Matrix of doubles to a la4j matrice/vector object.
public void fillData(int[][] data2D, int height, int width) throws IOException{
int[] data = initializeData(height, width);
double [][] coordinates = initializeDataCoordinates(height, width);
Matrix a = new Basic2DMatrix();
int index1d = 0;
for(int row = 0; row < height; row++){
for(int col = 0; col < width; col++){
int y = col+1;
int x = row+1;
//System.out.println("Current X: " + x);
//System.out.println("Current Y: " + y);
double xPow = Math.pow(x, 2);
double yPow = Math.pow(y, 2);
coordinates[row][0] = xPow*yPow;
coordinates[row][1] = x*yPow;
coordinates[row][2] = yPow;
coordinates[row][3] = xPow*y;
coordinates[row][4] = x*y;
coordinates[row][5] = y;
coordinates[row][6] = xPow;
coordinates[row][7] = x;
coordinates[row][8] = 1;
a.add((double)data2D[row][col]);
data[index1d] = data2D[row][col];
index1d++;
}
}
}
As you can see, I try to use the add method of the la4j lib but the matrice stays empty. My goal is to parse the whole content of double[][] coordinates and int[] data to la4j matrice and vector, respectivelly.
I have also tried parsing these to a CSV file but the scientific notation (due to extremely big numbers in my coordinates matrix) I can't parse it properly.
Any tips and ideas?
Here is the thing. First, you create 0x0 matrix with just call to the constructor new Basic2DMatrix(). Second, matrix.add is addition operation not insertion into the matrix (like matrix plus other matrix, or matrix plus value in your case). Calling matrix.add(value) adds given value to all the cells. In your case there is no cells in your matrix = nothing happened. All you need to do is call the constructor and pass the coordinates array there.
Matrix a = new Basic2DMatrix(coordinates); // easy-peasy
You can also use public access methods like get/set to manually set every element.
I am currently making a program to procedurally generate 2d terrain maps, with different technics such as perlin noise, simplex, voronoi, fractal noise, etc. on a size-defined image to be able to use it in my games requiring a 2d terrain.
I've come across the "Modelling fake planets" section of http://paulbourke.net/fractals/noise and I need to make it on a 2d texture, and not on a 3d world like it is explained.
Now I'm trying to
create a line from point 'X' to point 'Y'
That line will define a zone with a boolean value for left or right of the line to be "darker".
Doing that for a number of iteration to create a texture.
Using the RGB value of the final image to change stuffs such as forests, lakes, etc.
this would work this way:
overrides with this method below,
http://img35.imageshack.us/img35/24/islf.png
I used my high school maths powers to create a code sample but it's not really working...
Questions:
How should i change it so it works instead of just being failing?
Is there a simpler way than using what i am using?
Java file:
if i need an example on how i will proceed, here it is:
package Generator;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.util.Random;
import VectorialStuffs.Vector2;
public class Linear
{
public static BufferedImage generateImage(Dimension dim, int iterations)
{
BufferedImage image = new BufferedImage(dim.width, dim.height, BufferedImage.TYPE_INT_ARGB);
//point X and point Y
Vector2 pointX;
Vector2 pointY;
//difference between those
Vector2 diff;
Vector2 side;
double slope;
//random
Random rand = new Random();
boolean direction; //the orientation of the dark zone. (left/right)
for (int i = 0; i < iterations; ++i)
{
pointX = new Vector2(0, 0);
pointY = new Vector2(0, 0);
direction = rand.nextBoolean();
System.out.println(direction);
side = new Vector2(0, 0); //there are 4 sides of the image.
while (side.x == side.y)
{
side.x = rand.nextInt(3); //0 - 1 - 2 - 3
side.y = rand.nextInt(3);
}
switch(side.x) //not the x coord, the X point! ;D
{
//x = random and y = 0
case 0:
pointX.x = rand.nextInt(dim.width);
pointX.y = 0;
break;
//x = max and y = random
case 2:
pointX.x = dim.width;
pointX.y = rand.nextInt(dim.height);
break;
//x = random and y = max
case 1:
pointX.x = rand.nextInt(dim.width);
pointX.y = dim.height;
break;
//x = 0 and y = random
case 3:
pointX.x = 0;
pointX.y = rand.nextInt(dim.height);
break;
}
switch(side.y) //not the y coord, the Y point! ;D
{
//x = random and y = 0
case 0:
pointY.x = rand.nextInt(dim.width);
pointY.y = 0;
break;
//x = max and y = random
case 2:
pointY.x = dim.width;
pointY.y = rand.nextInt(dim.height);
break;
//x = random and y = max
case 1:
pointY.x = rand.nextInt(dim.width);
pointY.y = dim.height;
break;
//x = 0 and y = random
case 3:
pointY.x = 0;
pointY.y = rand.nextInt(dim.height);
break;
}
diff = new Vector2((pointY.x - pointX.x), (pointY.y - pointX.y));
slope = diff.y / diff.x;
Graphics graph = image.getGraphics();
if (direction) //true = right | false = left
{
int start; //the start x coordinate, on the line then increases until reaching the end of the image
int end = dim.width;
graph.setColor(Color.red);
graph.fillRect(pointX.x - 8, pointX.y -8, 16, 16);
graph.setColor(Color.yellow);
graph.fillRect(pointY.x - 8, pointY.y -8, 16, 16);
for (int times = 0; times < dim.height; ++times) //horizontal drawer
{
System.out.println(times);
start = (int)((times-diff.y)/slope + diff.y); //this is where it goes wrong?
for (int value = start; value < end; ++value)
{
graph.setColor(new Color(rand.nextInt(255), rand.nextInt(255), rand.nextInt(255), 100));
graph.fillRect(value, times, 1, 1);
}
}
graph.dispose();
}
else
{
int start; //the start x coordinate, on the line then increases until reaching the end of the image
int end = dim.width;
graph.setColor(Color.red);
graph.fillRect(pointX.x - 8, pointX.y -8, 16, 16);
graph.setColor(Color.yellow);
graph.fillRect(pointY.x - 8, pointY.y -8, 16, 16);
for (int times = 0; times < dim.height; ++times) //horizontal drawer
{
System.out.println(times);
start = (int)((times-diff.y)/slope);
for (int value = end; value < start; --value)
{
graph.setColor(new Color(rand.nextInt(255), rand.nextInt(255), rand.nextInt(255), 100));
graph.fillRect(value, times, 1, 1);
}
}
graph.dispose();
}
}
return image;
}
}
Note:
In this case vector2 is just a class with X and Y, which can be accessed (this is probably going to be temporary).
Startup part to avoid you losing time:
terrainImage = Linear.generateImage(size, 1); //size being a Dimension. -> "new Dimension(256, 256)"
if (terrainImage != null)
{
Icon wIcon = new ImageIcon(terrainImage);
JOptionPane.showMessageDialog(null, "message", "title", JOptionPane.OK_OPTION, wIcon);
}
//edit
here is the code that needs improvement:
if (direction) //true = right | false = left
{
int start; //the start x coordinate, on the line then increases until reaching the end of the image
int end = dim.width;
graph.setColor(Color.red);
graph.fillRect(pointX.x - 8, pointX.y -8, 16, 16);
graph.setColor(Color.yellow);
graph.fillRect(pointY.x - 8, pointY.y -8, 16, 16);
for (int times = 0; times < dim.height; ++times) //horizontal drawer
{
System.out.println(times);
start = (int)((times-diff.y)/slope + diff.y); //this is where it goes wrong?
for (int value = start; value < end; ++value)
{
graph.setColor(new Color(rand.nextInt(255), rand.nextInt(255), rand.nextInt(255), 100));
graph.fillRect(value, times, 1, 1);
}
}
graph.dispose();
}
else
{
int start; //the start x coordinate, on the line then increases until reaching the end of the image
int end = dim.width;
graph.setColor(Color.red);
graph.fillRect(pointX.x - 8, pointX.y -8, 16, 16);
graph.setColor(Color.yellow);
graph.fillRect(pointY.x - 8, pointY.y -8, 16, 16);
for (int times = 0; times < dim.height; ++times) //horizontal drawer
{
System.out.println(times);
start = (int)((times-diff.y)/slope);
for (int value = end; value < start; --value)
{
graph.setColor(new Color(rand.nextInt(255), rand.nextInt(255), rand.nextInt(255), 100));
graph.fillRect(value, times, 1, 1);
}
}
graph.dispose();
}
i can't get it to work like i showed in the picture above, all it does is either nothing, or offset from the 2 points.
Also, sometimes it freezes for no reason, so idk what will happen if i make more iterations of this :/
The pattern generation element of your code should only take about 3 lines, including rotation, colour pattern modulation and all as a function of iterations of i.
I will try and be clear:
you don't need a bar/line to generate your maps, you need any pattern on one/2 axes that starts off half of the period of the map and that gets a smaller and smaller proportion of the map or a smaller and smaller period.
pattern:
A line is round(x); or round (x+y) or round(sin(x+y +translatebar)+barwidth)<--a real bar in middle not just on side //
you can do curvy and zigzag lines later and 2D lines using additions and multiplications of X and Y functions. That function is essentially just a single line where you can change it X value so that rotates.
Rotation:
instead of a functional X every time which make a vertical line, you need to use sinus and co sinus function to generate X and Y values.
4 example 30; rotation is : round( X * 0.866+ Y* 0.5)
Get the sine and cosine of a random values and it will give you random rotations of your pattern the handy thing is that you just make a random value of your loop iteration and send it to a sign cosine.
OK i ll write this in pseudocode it will be simpler:
var pattern = 0; // black canvas
for(var i=1; i=100; i++)
{
pattern += round((sin (X*sin(pseudorand(i)) + Y*cos(pseudorand(i)) + translation) + roundshift )*strength;
}
The above loop will generate thousands of map patterns by adding bars of different rotations.
Round = quantizes your sin(XY) function so it is just black and white / red grey.
Sin(XY) = a variable function to use as a pattern, quantized by round to 0/1 values... multiply and clamp that value in the same line so it doesnt exceed 1 or 0
roundshift = value inside round(sin) pattern that shifts the sin down or up inside the round value resulting in smaller or larger amouts of black/white ration of each iteration. its a multiple of i so it's a function of i, gets smaller every loop.
xsin(rnd i) ycos(rnd i) = rotates your pattern both rnd's are same number necessarily.
translate value = when you +/- a number to a Sin(x+translate). it moves bar backwards/forwards
in the end your pattern value will equals maxiumum 100, so devide by 100 so it's 0-1 or mult by 2.56 for 256, and use a color randomiser to make RGB random multiples of your pattern value.
The above loop obviously needs to run once for every pixel x y.
i dont know how to do the canvas array/texture addin pixels in JS, it should be easy.
The above code will give you great patterns and visual feedback of your errors so you should be able to refine it very nicely, only think i missed is clamp to 0-1 values of sin (-1 1)+ roundshift result.
so a bar is round(sin(xy)+translate), and you can use many many functions of xy added muptiplied sins to add together everything else instead bars, graph circles, squares, wiggles, ovals, rectangles etc.
there is a website all about patterns of this type, except for ordered angles and say 5-6 iterations, using dots bars triangles etc, he is Canadian and on deviant art as well, if there weren't so many TD pattern generated I could find his website!
Here is a website explaining the process of "pattern piling" it's overlaying many shapes in smaller and smaller iterations.
only difference is he uses ordered rotations to create symmetry, and you want random rotations to create chaos maps.
see all the pics of piled patterns in 2d, he has many examples on deviant art and his site, i learnt alot from this guy:
http://algorithmic-worlds.net/info/info.php?page=pilpat
here is more work of superimposed smaller and smaller patterns in symmetry rotations:
https://www.google.com/search?q=Samuel+Monnier&espv=210&es_sm=93&source=lnms&tbm=isch&sa=X&ei=It0AU9uTCOn20gXXv4G4Cw&ved=0CAkQ_AUoAQ&biw=1365&bih=911
same as this using random sin cos rotations.
I'm running an example from a Kinect library for Processing (http://www.shiffman.net/2010/11/14/kinect-and-processing/) and sometimes get a NullPointerException pointing to this line:
int rawDepth = depth[offset];
The depth array is created in this line:
int[] depth = kinect.getRawDepth();
I'm not exactly sure what a NullPointerException is, and much googling hasn't really helped. It seems odd to me that the code compiles 70% of the time and returns the error unpredictably. Could the hardware itself be affecting it?
Here's the whole example if it helps:
// Daniel Shiffman
// Kinect Point Cloud example
// http://www.shiffman.net
// https://github.com/shiffman/libfreenect/tree/master/wrappers/java/processing
import org.openkinect.*;
import org.openkinect.processing.*;
// Kinect Library object
Kinect kinect;
float a = 0;
// Size of kinect image
int w = 640;
int h = 480;
// We'll use a lookup table so that we don't have to repeat the math over and over
float[] depthLookUp = new float[2048];
void setup() {
size(800,600,P3D);
kinect = new Kinect(this);
kinect.start();
kinect.enableDepth(true);
// We don't need the grayscale image in this example
// so this makes it more efficient
kinect.processDepthImage(false);
// Lookup table for all possible depth values (0 - 2047)
for (int i = 0; i < depthLookUp.length; i++) {
depthLookUp[i] = rawDepthToMeters(i);
}
}
void draw() {
background(0);
fill(255);
textMode(SCREEN);
text("Kinect FR: " + (int)kinect.getDepthFPS() + "\nProcessing FR: " + (int)frameRate,10,16);
// Get the raw depth as array of integers
int[] depth = kinect.getRawDepth();
// We're just going to calculate and draw every 4th pixel (equivalent of 160x120)
int skip = 4;
// Translate and rotate
translate(width/2,height/2,-50);
rotateY(a);
for(int x=0; x<w; x+=skip) {
for(int y=0; y<h; y+=skip) {
int offset = x+y*w;
// Convert kinect data to world xyz coordinate
int rawDepth = depth[offset];
PVector v = depthToWorld(x,y,rawDepth);
stroke(255);
pushMatrix();
// Scale up by 200
float factor = 200;
translate(v.x*factor,v.y*factor,factor-v.z*factor);
// Draw a point
point(0,0);
popMatrix();
}
}
// Rotate
a += 0.015f;
}
// These functions come from: http://graphics.stanford.edu/~mdfisher/Kinect.html
float rawDepthToMeters(int depthValue) {
if (depthValue < 2047) {
return (float)(1.0 / ((double)(depthValue) * -0.0030711016 + 3.3309495161));
}
return 0.0f;
}
PVector depthToWorld(int x, int y, int depthValue) {
final double fx_d = 1.0 / 5.9421434211923247e+02;
final double fy_d = 1.0 / 5.9104053696870778e+02;
final double cx_d = 3.3930780975300314e+02;
final double cy_d = 2.4273913761751615e+02;
PVector result = new PVector();
double depth = depthLookUp[depthValue];//rawDepthToMeters(depthValue);
result.x = (float)((x - cx_d) * depth * fx_d);
result.y = (float)((y - cy_d) * depth * fy_d);
result.z = (float)(depth);
return result;
}
void stop() {
kinect.quit();
super.stop();
}
And here are the errors:
processing.app.debug.RunnerException: NullPointerException
at processing.app.Sketch.placeException(Sketch.java:1543)
at processing.app.debug.Runner.findException(Runner.java:583)
at processing.app.debug.Runner.reportException(Runner.java:558)
at processing.app.debug.Runner.exception(Runner.java:498)
at processing.app.debug.EventThread.exceptionEvent(EventThread.java:367)
at processing.app.debug.EventThread.handleEvent(EventThread.java:255)
at processing.app.debug.EventThread.run(EventThread.java:89)
Exception in thread "Animation Thread" java.lang.NullPointerException
at org.openkinect.processing.Kinect.enableDepth(Kinect.java:70)
at PointCloud.setup(PointCloud.java:48)
at processing.core.PApplet.handleDraw(PApplet.java:1583)
at processing.core.PApplet.run(PApplet.java:1503)
at java.lang.Thread.run(Thread.java:637)
You are getting a NullPointerException since the value of the depth array is null. You can see from the source code of the Kinect class, there is a chance of a null value being returned by the getRawDepth() method. It is likely that there is no image being displayed at the time.
The code can be found at:
https://github.com/shiffman/libfreenect/blob/master/wrappers/java/processing/KinectProcessing/src/org/openkinect/processing/Kinect.java
Your code should check if the depth array is null before trying to process it. For example...
int[] depth = kinect.getRawDepth();
if (depth == null) {
// do something here where you handle there being no image
} else {
// We're just going to calculate and draw every 4th pixel (equivalent of 160x120)
int skip = 4;
// Translate and rotate
translate(width/2,height/2,-50);
rotateY(a);
for(int x=0; x<w; x+=skip) {
for(int y=0; y<h; y+=skip) {
int offset = x+y*w;
// Convert kinect data to world xyz coordinate
int rawDepth = depth[offset];
PVector v = depthToWorld(x,y,rawDepth);
stroke(255);
pushMatrix();
// Scale up by 200
float factor = 200;
translate(v.x*factor,v.y*factor,factor-v.z*factor);
// Draw a point
point(0,0);
popMatrix();
}
}
// Rotate
a += 0.015f;
}
I would suggest using a Java Debugger so that you can see the state of the variables at the time the exception is thrown. Some people also like to use log statements to output the values of the variables at different points in the application.
You can then trace the problem back to a point where one of the values is not populated with a non-null value.
The null pointer is happening when offset > kinect.getRawDepth();
You have a lot of code here, I'm not going to look at it all. Why can you assume that offset is < kinect.getRawDepth()?
Edit:
On second though, #Asaph's comment is probably right.
Null Pointer exception happens when depth[offset] does not exist or has not been allocated. Check when depth[offset] is undefined and that is the cause of the nullpointer exception.
Check when kinect.getRawDepth(); is greater than offset.