We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProgramming Questions & HelpPrograms › pixel silhouette to shape
Page Index Toggle Pages: 1
pixel silhouette to shape (Read 1669 times)
pixel silhouette to shape
Nov 3rd, 2009, 10:32am
 
Hi,

what i'm trying to do is to make a shape out of a silhouette which i got by background substraction.
I do store the edges of the silhouette in x[] and y[] - but: when i store those, they are quite messy, as i do it line by line.
does anybody know a nice way how i can get a shape out of this? or in general how to make a vector out of a pixel-blob?

Code:
/* This is the example of background substraction by golan levin; 
i just messed around a little bit. after having started the sketch
press SPACE(!) to get an background image. after this the blob is
green and in x[] and y[] the edges are stored. out of those i'd
like to do my shape.*/

import processing.video.*;
import controlP5.*;
/* if you don't got the control P5 thing than delete all the stuff out
sliderValue is the treshold*/
int sliderValue = 60;

int numPixels;
int[] backgroundPixels;
Capture video;

ControlP5 controlP5;
ControlWindow controlWindow;

int num = 0;
int[] x = new int[0];
int[] y = new int[0];
boolean once = false;

void setup() {
size(320, 240, P2D);

//threshold slider
controlP5 = new ControlP5(this);
controlWindow = controlP5.addControlWindow("settings", 500, 100, 490, 180);
controlWindow.setBackground(color(0));
Slider s = controlP5.addSlider("sliderValue",0,255,60,40,120,350,20);
s.setWindow(controlWindow);

video = new Capture(this, width, height, 24);
numPixels = video.width * video.height;
// Create array to store the background image
backgroundPixels = new int[numPixels];
// Make the pixels[] array available for direct manipulation
loadPixels();
}

void draw() {
if (video.available()) {
video.read();
video.loadPixels();
int presenceSum = 0;

//j does count the lines
int j = 0;

x = new int[0];
y = new int[0];

for (int i = 0; i < numPixels; i++) {

// ----background substraction as in the example by Golan Levin-------
color currColor = video.pixels[i];
color bkgdColor = backgroundPixels[i];
// Extract the red, green, and blue components of the current pixel’s color
int currR = (currColor >> 16) & 0xFF;
int currG = (currColor >> 8) & 0xFF;
int currB = currColor & 0xFF;
// Extract the red, green, and blue components of the background pixel’s color
int bkgdR = (bkgdColor >> 16) & 0xFF;
int bkgdG = (bkgdColor >> 8) & 0xFF;
int bkgdB = bkgdColor & 0xFF;
// Compute the difference of the red, green, and blue values
int diffR = abs(currR - bkgdR);
int diffG = abs(currG - bkgdG);
int diffB = abs(currB - bkgdB);

pixels[i] = 0xFF000000 | (diffR << 16) | (diffG << 8) | diffB;
// -------------------------------------------------------------------


//------------------starting to mess around---------------------------
if (diffR > sliderValue || diffG > sliderValue || diffB > sliderValue){ //make the silhouette green
pixels[i] = color(0,255,0);

if(j > 0 && (pixels[i-1] != color(0,255,0))){ //quick and dirty edge detection from black to green
x = append(x, i-((j-1)*width)); //getting x, when pixel changes from black to green
y = append(y, j); //same with y
}
}

if(j > 0 && pixels[i-1] == color(0,255,0) && pixels[i] != color(0,255,0)){ //quick and dirty edge detection from green to black
x = append(x, i-((j-1)*width)); //getting x, when pixel changes from green to black
y = append(y, j); //same with y
}

if(i > width && i > j*width) j++; //count the lines we got
}
updatePixels(); // Notify that the pixels[] array has changed

//here is where i somehow would like to do an silhouette out of all those x and y i got
//but curently its only rectangles
noStroke();
fill(255,0,0);
//beginShape();
for (int i = 0; i < x.length; i++){
rect(x[i], y[i], 10,10);
}
//endShape();
noFill();
}
}


void keyPressed() {
if (key == ' '){
video.loadPixels();
arraycopy(video.pixels, backgroundPixels);
}
if (key == 'e') exit();
}
Re: pixel silhouette to shape
Reply #1 - Nov 3rd, 2009, 11:51am
 
By "vector," do mean a vector (not bitmap) image?  If you can identify the edges of your blob, say by examining each pixel to see if it neighbors a background pixel, you could generate lines between all adjacent border-pixels...
Not sure what you mean by messy storage / line by line.  If you're saving the pixel array, it should be an exact copy..
Re: pixel silhouette to shape
Reply #2 - Nov 4th, 2009, 1:40am
 
Hi,

may be i was a little bit confusing:
what i mean by vector is, that i want to make a shape with the beginShap() and endShape() funktion. to do this i would need to have the vertices in a certain order.
what i have now is an array with this order:

x[0] = first x-coordinate in line one
x[1] = second x in line one
x[2] = first x in line two
x[3] = 2nd x in line two
x[4] = 3rd x in line two
x[5] = 4th x in line two
.
.
.

however, when having a complex shape, i can have lots of coordinates in one line. so i'd need to have a certain algorithm to change to something like this:

vertex(x[0], y[0])
vertex(x[2], y[2])
.
.

you know, so that all the first vertices of each line are connected, than the last ones, than the middle ones, etc.
in the end i'd make kind of a line AROUND the blob.

at least this would be the way i'd try it now. but may be there is an algorithm, that is much easier than the way i'm thinking...
Re: pixel silhouette to shape
Reply #3 - Nov 4th, 2009, 10:37am
 
If you have concave areas in your shapes, I'd try the method I mentioned...but if you have more complexity than that (like shapes within shapes, or cutouts), watch out.
Re: pixel silhouette to shape
Reply #4 - Nov 4th, 2009, 2:21pm
 
Hi there, below is my first try on shape-recognition from today. It doesn't work good when multiple forms are on the same height, i guess thats because an logic error in the algorithm, but i can't find it Cheesy

cam.pde:
Code:
import processing.video.*;

Capture video;
Form[] f = new Form[0];

void setup() {
size(640, 480);
video = new Capture(this, width, height, 10);
noStroke();
smooth();
ellipseMode(CENTER);
}

void draw() {
//background(255);
if (video.available()) {
f = new Form[0];
video.read();
image(video, 0, 0, width, height);
video.loadPixels();
int index = 0;
int raster = 4;
for (int y = 0; y < video.height; y+=raster) {
for (int x = 0; x < video.width; x+=raster) {
int pixelValue = video.pixels[y*video.width+x];
boolean intresting = brightness(pixelValue)<80;
if (intresting) {
boolean old_spot = false;
for (int i=0; i<f.length && !old_spot ; i++){
Form fi = f[i];
int row = fi.v.length-1;
int dx = x-fi.v[row][1];
int dy = y-fi.v[row][2];
if (dx<=2*raster && dy<=2*raster) {
old_spot = true;
if (fi.v[row][2]<y) {
fi.addRow(x,y);
}
else {
fi.v[row][1] = x;
}
}
}
if (!old_spot) {
Form new_form = new Form(x,y);
f = (Form[]) append(f,new_form);
}
}
}
}

}
for (int i=0; i<f.length; i++) {
f[i].draw(i);
}
}

void keyPressed() {
for (int i=0; i<f.length; i++) {
print(f[i]);
}
}


Form.pde
Code:
class Form {
int[][] v = new int[0][3];
int y;
color c;
Form(int x,int y) {
this.y = y;
addRow(x,y);
this.c = lerpColor(#ff0000,#0000ff,1);
}

void addRow(int x, int y) {
int[] v_n = new int[3];
v_n[0] = x;
v_n[1] = x;
v_n[2] = y;
v = (int[][]) append(v, v_n);
}

void draw(int nr) {
line(v[0][0],v[0][2],v[0][1],v[0][2]);
for (int i=0;i<v.length-1;i++){
stroke(c,35);
strokeWeight(4);
line(v[i][0],v[i][2],v[i+1][0],v[i+1][2]);
line(v[i][1],v[i][2],v[i+1][1],v[i+1][2]);
}
line(v[v.length-1][0],v[v.length-1][2],v[v.length-1][1],v[v.length-1][2]);
}

String toString() {
String a = "------------START---------\n";
for (int i=0;i<v.length-1;i++){
a+="["+v[i][0]+"|"+v[i][1]+"|"+v[i][2]+"]\n";
}
a +="------------END-----------\n";
return a;
}
}

Page Index Toggle Pages: 1