Ok guys I am almost there but got stuck, from this link
http://en.wikipedia.org/wiki/Image_gradient they said I can use the
Sobel Operator to get the gradient values, so I did.
I manage to get the same results using the same image like they show here
http://en.wikipedia.org/wiki/Sobel_operator, so far so good.
From the algorithm I post previously, they said
Quote:1.Convolution with a 3x3 kernel, y-1 and y+1 as 1,div by 2 bias 127, copy to red channel
2.Convolution with a 3x3 kernel x-1 and x+1 as 1, div by 2, bias 127, copy to blue channel
So I did (I think)
Code:for (int x = 1; x < width - 1; x++) { // Skip left and right edges
for (int y = 1; y < height - 1; y++) { // Skip top and bottom edges
float cX = convolution(x, y, kernelX, noiseImg);
float cY = convolution(x, y, kernelY, noiseImg);
cX = (cX / 2.0) - 127.0;
cY = (cY / 2.0) - 127.0;
// gradient vector
PVector c = new PVector(cX, cY);
// For this pixel in the new image, set the gray value
// based on the sum from the kernel
sobelImg.pixels[y * width + x] = color(c.mag());
}
}
Here is the important bitThe gradient image looks right, but if I print the results at a specific mouse location, I get negative values, and that is not right, because if using the sobel operator I get a gradient vector, and use this gradient vector to move the particles, they will always go to the top-left
Here is the sketch, please note that I haven't done any optimization
Code:import toxi.math.noise.*;
// sobel operator kernels
// http://en.wikipedia.org/wiki/Sobel_operator
float[][] kernelX = { { 1, 0, -1 },
{ 2, 0, -2 },
{ 1, 0, -1 } };
float[][] kernelY = { { 1, 2, 1 },
{ 0, 0, 0 },
{ -1, -2, -1 } };
float NS = 0.01; // noise scale (try from 0.005 to 0.5)
float noiseOffset = 100.0;
PImage noiseImg, sobelImg;
void setup() {
size(300, 225, P3D);
}
void draw() {
// generate noise canvas
noiseImg = createImage(width, height, RGB);
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
float noiseVal = 0.0;
// for noise motion add noiseOffset
//noiseVal = (float)SimplexNoise.noise(i * NS + noiseOffset, j * NS + noiseOffset, frameCount * 0.02);
// for static noise
noiseVal = (float)SimplexNoise.noise(i * NS, j * NS, frameCount * 0.02);
int c = (int)(noiseVal * 127 + 128);
noiseImg.set(i, j, c << 16 | c << 8 | c | 0xff000000);
}
}
// render noise image
//image(noiseImg, 0, 0);
noiseImg.loadPixels();
// Create an opaque image of the same size as the original
sobelImg = createImage(width, height, RGB);
// Loop through every pixel in the image.
for (int x = 1; x < width - 1; x++) { // Skip left and right edges
for (int y = 1; y < height - 1; y++) { // Skip top and bottom edges
float cX = convolution(x, y, kernelX, noiseImg);
float cY = convolution(x, y, kernelY, noiseImg);
cX = (cX / 2.0) - 127.0;
cY = (cY / 2.0) - 127.0;
// gradient vector
PVector c = new PVector(cX, cY);
// For this pixel in the new image, set the gray value
// based on the sum from the kernel
sobelImg.pixels[y * width + x] = color(c.mag());
}
}
sobelImg.updatePixels();
// render sobel resulting image
image(sobelImg, 0, 0);
if (mousePressed) {
float cX = convolution((int)mouseX, (int)mouseY, kernelX, noiseImg);
float cY = convolution((int)mouseX, (int)mouseY, kernelY, noiseImg);
cX = (cX / 2.0) - 127.0;
cY = (cY / 2.0) - 127.0;
PVector c = new PVector(cX, cY);
//c.normalize();
println(c);
}
//println("fps: " + frameRate);
}
float convolution(int x, int y, float[][] kernel, PImage img) {
float sum = 0.0; // Kernel sum for this pixel
for (int kx = -1; kx <= 1; kx++) {
for (int ky = -1; ky <= 1; ky++) {
// Calculate the adjacent pixel for this kernel point
int pos = (x + kx) + (y + ky) * width;
// Image is grayscale, red/green/blue are identical
//float val = red(img.pixels[pos]);
float val = img.pixels[pos] >> 16 & 0xFF;
// Multiply adjacent pixels based on the kernel values
sum += kernel[ky + 1][kx + 1] * val;
}
}
return sum;
}
Hope that makes any sense, and any help at this point will be much appreciated
Cheers
rS