Forums > Jitter

making a 'vector outline' from a silhouette.

February 15, 2006 | 4:38 am

I’m wanting to turn a live video feed of the silhouette of a body into a vector outline.

I’m grabbing a live video image and converting into a single plane high-contrast image. So the body is black and the surrounding area is white.

I want to do some kind of edge detection that gives me the co-ordinates of the black-white edge. But I want to list them in order so that if I joined them up using the lineto command in gl.sketch I would get a nice continuous shape.

A bit like ‘join-the-dots’. So that an outline of the figure can be drawn live.

I’ve been pointed towards Cyclops, but I’m not sure this is right.

All ideas most appreciated.


February 15, 2006 | 5:44 am

In a perfect world, the following would work:

1) Take your silhohuette, threshold it to get a binary image
2) take the gradient of the binary image (you can probably do just
fine with jit.sobel, if not, you can use the finite difference
method..if you do use this method, I can send you an object that does
it)
3) Threshold the gradient to get just the edge pixels
4) spit out the cell coordinates of the edge pixels ( you can use
xray.jit.cellcoord)
5) convert from pixel to opengl coordinates
6) draw

Problems you might encounter:
1)Image has noise, need to smooth it first. Try a median filter. I
can send you one of these too if you need it.
2)too many coordinates (oversampling)–>try out jit.demultiplex, but
this might cause you to lose smaller shapes like fingers and feet.
3) probably more issues, but no more come to mind.

good luck,
wes


February 15, 2006 | 5:59 am

> 2)too many coordinates (oversampling)–>try out jit.demultiplex, but
> this might cause you to lose smaller shapes like fingers and feet.

it would be worthwhile to try downsampling the image (pre-edge detect
would be more cpu efficient, but could give better quality?) to a low
resolution – play with the dim message that works best…no need to be
a slave to 4×3!

it is nice to know about the xray.jit.cellcoord. i started to reply to
this email with a gedanken patch, but my brain got lazy/stumped at how
to pull just the white coords w/ jitter’s obejct set. Looks like wes
solved that one, too.

p.


February 15, 2006 | 7:14 am

You guys are working way too hard… Happy Valentine’s.

Andrew B.

#P window setfont "Sans Serif" 9.;
#P user jit.fpsgui 41 209 60 196617 0;
#P user jit.pwindow 147 272 82 62 0 1 0 0 1 0;
#P flonum 315 178 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P window linecount 1;
#P newex 237 201 63 196617 jit.op @op >;
#B color 5;
#P newex 237 181 66 196617 jit.rgb2luma;
#B color 5;
#P newex 238 222 151 196617 jit.matrix 1 float32 320 240 2;
#B color 5;
#P newex 103 106 75 196617 jit.window foo;
#P toggle 41 81 15 0;
#P newex 41 105 51 196617 qmetro 5;
#P newex 41 130 95 196617 t erase b b;
#P newex 41 182 195 196617 jit.gl.render foo @erase_color 1. 1. 1. 1.;
#P newex 238 256 331 196617 jit.gl.isosurf foo @scale 1.333 -1. 0.1 @dim 80 60 2 @color 0. 0. 0. 1.;
#P flonum 260 99 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P message 260 119 42 196617 rate $1;
#P message 320 99 28 196617 read;
#P newex 237 157 103 196617 jit.qt.movie 320 240;
#B color 5;
#P fasten 6 2 0 0 130 151 242 151;
#P connect 6 0 5 0;
#P fasten 6 1 5 0 88 158 46 158;
#P connect 7 0 6 0;
#P connect 10 0 4 0;
#P connect 12 0 14 0;
#P connect 12 0 10 0;
#P connect 5 0 15 0;
#P connect 13 0 12 1;
#P connect 11 0 12 0;
#P connect 0 0 11 0;
#P connect 8 0 7 0;
#P connect 3 0 2 0;
#P fasten 1 0 0 0 325 146 242 146;
#P fasten 2 0 0 0 265 146 242 146;
#P window clipboard copycount 16;


February 15, 2006 | 7:47 am

That’s pretty cool. You love that isosurf object don’t you!

wes


February 15, 2006 | 3:45 pm

*blush*

I love all of Jitter’s children.

;)
AB


February 15, 2006 | 8:27 pm

And here’s a little toy begat from Andrew’s example:
http://www.killingfrenzy.com/Jitter/Vectorizer.zip
Sloppy, but fun to play with.
Beware the "detail" setting on slower machines.


February 16, 2006 | 2:10 am

Marvellous help so far.

Couldn’t get Andrew’s thing to open. (could see foo window but couldn’t see the patch window). But the vectorizer patch is definitely a step in the right direction.

But I want to be able to access the individual points that make up the shape. So isosurf is doing exactly the right thing in that it’s making a shape from the silhouette. But I haven’t got access to the data that makes up the shape.

I started off making a patch like wesley’s suggestion (listed underneath).

I can get all of the coordinates and get them to draw a shape, but they aren’t nicely sorted as they are in the isosurf examples. They just come out in matrix order. So when you use lineto in jit.gl.sketch, it draws the lines in matrix order, rather than the elegant outline manner of the isosurf example.

How do I get the isosurf object to spit out the nicely sorted list of opengl coordinates it is using to draw the shape?

The reason I need to do this is that I want to use the convert the co-ordinates into control voltages to send to an oscilloscope-type device.

Currently I’m doing this through a soundcard that allows DC offset.

Here’s my crap patch that doesn’t work at all well, just to show you where I’ve been….

again, thanks for the help so far….

max v2;
#N vpatcher 170 84 933 823;
#P origin 40 27;
#P window setfont "Sans Serif" 9.;
#P window linecount 1;
#P newex 16 136 129 196617 jit.matrix 4 char 160 120;
#P window linecount 0;
#P newex 520 64 50 196617;
#P button 345 297 15 0;
#P window linecount 1;
#P newex 409 404 82 196617 pack lineto 0. 0.;
#P flonum 491 302 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 428 339 29 196617 * 1.;
#P newex 489 339 29 196617 * 1.;
#P newex 428 304 40 196617 unpack;
#P newex 414 487 32 196617 print;
#P window linecount 0;
#P newex 438 119 50 196617;
#P window linecount 1;
#P newex 558 470 73 196617 prepend lineto;
#P newex 825 143 49 196617 r dotsize;
#P newex 814 53 71 196617 r drawshape1;
#P message 824 170 69 196617 point_size $1;
#P flonum 873 349 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P flonum 835 350 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P flonum 797 350 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 796 386 60 196617 pak 0. 0. 0.;
#P newex 796 411 80 196617 prepend camera;
#P toggle 755 245 15 0;
#P user jit.fpsgui 816 473 60 196617 0;
#P newex 756 294 43 196617 jit.qball;
#P number 801 239 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 756 271 55 196617 metro 20;
#P newex 756 325 55 196617 t b erase b;
#P newex 771 509 160 196617 jit.window marcus 5 41 320 281;
#P newex 778 446 100 196617 jit.gl.render marcus;
#P newex 764 197 99 196617 jit.gl.sketch marcus;
#P newex 346 267 79 196617 select 255 1 0;
#P newex 413 183 41 196617 jit.iter;
#P newex 534 183 48 196617 jit.bsort;
#P flonum 107 199 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P message 107 219 52 196617 thresh $1;
#P newex 19 270 64 196617 jit.robcross;
#P user jit.fpsgui 23 639 60 196617 0;
#P message 259 93 17 196617 1.;
#P flonum 160 128 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P flonum 237 128 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P message 160 147 70 196617 brightness $1;
#P message 237 147 61 196617 contrast $1;
#P newex 4 177 52 196617 jit.brcosa;
#B color 5;
#P newex 4 220 66 196617 jit.unpack;
#P user jit.pwindow 17 346 322 242 0 1 0 0 1 0;
#P message 64 42 28 196617 read;
#P message 134 42 27 196617 stop;
#P message 100 42 31 196617 start;
#P toggle 1 21 15 0;
#P newex 1 41 44 196617 metro 2;
#P newex 1 105 103 196617 jit.qt.movie 320 240;
#B color 5;
#P connect 2 0 1 0;
#P fasten 1 0 0 0 6 71 6 71;
#P fasten 3 0 0 0 105 68 6 68;
#P fasten 4 0 0 0 139 68 6 68;
#P fasten 5 0 0 0 69 68 6 68;
#P connect 48 0 8 0;
#P fasten 9 0 8 0 242 172 9 172;
#P fasten 10 0 8 0 165 172 9 172;
#P connect 8 0 7 0;
#P connect 0 0 48 0;
#P connect 15 0 6 0;
#P connect 16 0 15 0;
#P connect 7 1 15 0;
#P connect 6 0 14 0;
#P connect 17 0 16 0;
#P fasten 13 0 12 0 264 118 165 118;
#P connect 12 0 10 0;
#P fasten 13 0 11 0 264 118 242 118;
#P connect 11 0 9 0;
#P connect 20 0 46 0;
#P connect 19 0 20 0;
#P connect 46 0 45 0;
#P connect 19 1 41 0;
#P connect 41 0 43 0;
#P connect 43 0 45 1;
#P connect 44 0 43 1;
#P connect 42 0 45 2;
#P connect 41 1 42 0;
#P connect 44 0 42 1;
#P connect 29 0 25 0;
#P connect 25 0 27 0;
#P connect 27 0 24 0;
#P connect 45 0 21 0;
#P connect 35 0 21 0;
#P connect 36 0 21 0;
#P connect 24 1 22 0;
#P connect 30 0 22 0;
#P connect 24 0 22 0;
#P connect 32 0 31 0;
#P connect 31 0 30 0;
#P connect 26 0 25 1;
#P connect 24 2 28 0;
#P connect 33 0 31 1;
#P connect 37 0 35 0;
#P connect 34 0 31 2;
#P pop;


February 16, 2006 | 3:06 am

Hello Marcus,

Can you elaborate this (if you don’t mind of course) since I am kind
of curious what you mean by oscilloscope-type device.
Thank you so much!

ilteris.


February 16, 2006 | 4:23 am

Well. it’s an oscilloscope at the moment. But it might end up being a dangerously modified CRT projector.


February 16, 2006 | 4:57 am

and I forgot to join jit.robcross to jit.iter in my patch.


February 16, 2006 | 5:23 am

Hi Marcus,
Here’s some things I noticed about your patch. If possible, do math
operations in matrix form. They’re much faster than doing them in max
messages. Second, jit.iter is always a bottleneck for large matrices
(meaning > say 20 cells). Instead, hook your matrix up to jit.gl.mesh
and render lines that way.

I also noticed you had a jit.bsort object in your patch. If you
decide you need to sort your matrix, I would recommend against using
jit.bsort since it’s quite a slow sorting algorithm. I would instead
use xray.jit.quicksort. It’s several times faster. The the patch
below, I used xray.jit.cellcoords to grab white cells. You can
download it here: http://www.mat.ucsb.edu/~whsmith/ .

Here’s a crude response:

#P window setfont "Sans Serif" 9.;
#P window linecount 1;
#P newex 406 387 136 196617 jit.op @op / @val 160 -160;
#P newex 106 310 106 196617 jit.op @op > @val 0.3;
#P newex 226 336 158 196617 xray.jit.cellcoords @out_mode 1;
#P newex 446 449 204 196617 jit.gl.mesh marcus @draw_mode line_strip;
#P newex 16 196 129 196617 jit.matrix 4 char 160 120;
#P flonum 873 409 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P flonum 835 410 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P flonum 797 410 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 796 446 60 196617 pak 0. 0. 0.;
#P newex 796 471 80 196617 prepend camera;
#P toggle 755 305 15 0;
#P user jit.fpsgui 816 533 60 196617 0;
#P newex 756 354 43 196617 jit.qball;
#P number 801 299 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 756 331 55 196617 metro 20;
#P newex 756 385 55 196617 t b erase b;
#P newex 771 569 160 196617 jit.window marcus 5 41 320 281;
#P newex 778 506 100 196617 jit.gl.render marcus;
#P newex 534 243 48 196617 jit.bsort;
#P flonum 107 259 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P message 107 279 52 196617 thresh $1;
#P newex 19 330 64 196617 jit.robcross;
#P user jit.fpsgui 23 699 60 196617 0;
#P message 259 153 17 196617 1.;
#P flonum 160 188 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P flonum 237 188 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P message 160 207 70 196617 brightness $1;
#P message 237 207 61 196617 contrast $1;
#P newex 4 237 52 196617 jit.brcosa;
#B color 5;
#P newex 4 280 66 196617 jit.unpack;
#P user jit.pwindow 17 406 322 242 0 1 0 0 1 0;
#P message 64 102 28 196617 read;
#P message 134 102 27 196617 stop;
#P message 100 102 31 196617 start;
#P toggle 1 81 15 0;
#P newex 1 101 44 196617 metro 2;
#P newex 1 165 103 196617 jit.qt.movie 320 240;
#B color 5;
#P connect 36 0 33 0;
#P connect 34 0 36 0;
#P connect 35 0 6 0;
#P connect 35 0 34 0;
#P connect 15 0 35 0;
#P connect 7 1 15 0;
#P connect 31 0 28 2;
#P connect 30 0 28 1;
#P connect 21 2 25 0;
#P connect 23 0 22 1;
#P connect 28 0 27 0;
#P connect 29 0 28 0;
#P connect 21 0 19 0;
#P connect 27 0 19 0;
#P connect 21 1 19 0;
#P connect 24 0 21 0;
#P connect 22 0 24 0;
#P connect 26 0 22 0;
#P connect 11 0 9 0;
#P fasten 13 0 12 0 264 178 165 178;
#P fasten 13 0 11 0 264 178 242 178;
#P connect 12 0 10 0;
#P connect 17 0 16 0;
#P connect 6 0 14 0;
#P connect 16 0 15 0;
#P connect 0 0 32 0;
#P connect 8 0 7 0;
#P fasten 10 0 8 0 165 232 9 232;
#P fasten 9 0 8 0 242 232 9 232;
#P connect 32 0 8 0;
#P fasten 5 0 0 0 69 128 6 128;
#P fasten 4 0 0 0 139 128 6 128;
#P fasten 3 0 0 0 105 128 6 128;
#P fasten 1 0 0 0 6 131 6 131;
#P connect 2 0 1 0;
#P window clipboard copycount 37;


February 16, 2006 | 5:56 am

BTW, you can always do @matrixoutput 1 on jit.gl.isosurf.

wes


February 16, 2006 | 6:03 am

It’s funny that only text is shown when I open the saved patch.
Am I missing any module not installed ?

William


February 16, 2006 | 7:59 am

The X-ray objects are well worth having.

http://www.mat.ucsb.edu/~whsmith/

xray.jit.cellcoord
is in the patch.


February 16, 2006 | 8:23 am

I have been playing with X-ray objects happily now, but the problem on
loading the saved patch presist.

I guess the patch missed a few lines like,
– max v2;
– #N vpatcher 211 99 758 452;
right ?

By the way, I have looked into another project Wesley has done,
"A-Contrario". The description of what it does is very interesting, but the
project file downloadable doesn’t work in my PC. Wesley, any chance we may
get a windows version of the project ? We are missed "xray.jit.probsegment"
and "xray.jit.median" to have it run.

^_^
William


February 16, 2006 | 8:30 am

> I guess the patch missed a few lines like,
> — max v2;
> — #N vpatcher 211 99 758 452;
> right ?

What version of Max are you running?? The patch code pasted was from
the clipboard and only works with the newer versions on Max (I think
4.5 and >, but I could be wrong). Basically, it’s not a full patcher
but a patcher chunk.

> By the way, I have looked into another project Wesley has done,
> "A-Contrario". The description of what it does is very interesting, but the
> project file downloadable doesn’t work in my PC. Wesley, any chance we may
> get a windows version of the project ? We are missed " xray.jit.probsegment"
> and "xray.jit.median" to have it run.
>

True, these 2 objects are not compiled on a PC yet. I’ll see if I
can’t find time this weekend to do it.

wes


February 16, 2006 | 10:43 am

> What version of Max are you running?? The patch code pasted was from
> the clipboard and only works with the newer versions on Max (I think
> 4.5 and >, but I could be wrong). Basically, it’s not a full patcher
> but a patcher chunk.

I am using the latest version of Max/Jitter. Maybe I am too green on using
the program, I don’t know the different between patcher and patcher chunk.

I always copy and paste the texts into a text file and save with .pat
extension. Usually it will work when I open it, but sometimes it fails with
only text displayed. _|~~|O

> True, these 2 objects are not compiled on a PC yet. I’ll see if I
> can’t find time this weekend to do it.

great to hear that~ thanks first~

^_^,
William


February 16, 2006 | 4:06 pm

On 2/16/06, William Wong wrote:
> > What version of Max are you running?? The patch code pasted was from
> > the clipboard and only works with the newer versions on Max (I think
> > 4.5 and >, but I could be wrong). Basically, it’s not a full patcher
> > but a patcher chunk.
>

Sorry, those weren’t technical terms. If you’re using the latest max,
you should be able to open a new patcher window and paste the text in
there. The text will magically become a patcher.

wes


February 17, 2006 | 1:27 am

Thanks for all the excellent advice so far.

For any newbies (like myself) following this thread, I’ve run into a couple of issues.

I installed the xray objects but couldn’t see them in max.

So I built an object list and put it into the cycling74/init folder. Bingo!

Couldn’t find one with the installer. This one isn’t very elegant (sorry Wes) but seems to do the trick.

But my main issue is that if I open the patches that have been posted, I only see a jit.window and not the patch itself.

Same problem on Andrew and Wes’s patches. Thought it had something to do with the lines at the top of the text. I’m assuming these refer to where the patcher window appears.

I thought that because I’m on a little powerbook, maybe the patcher window was out of sight. So edited the text so that it’s the same as the patch I posted. Still no joy…..

I’m probably missing something very obvious here…..


February 17, 2006 | 1:52 am

> I installed the xray objects but couldn’t see them in max.
>
Do you mean they didn’t show up in the New Object List? Or when you
right click on the patcher background? If you put the objects in
/jitter-externals/xray then they are definitely in your search path
and you should be able to use them without having to make a list.
Personally, I don’t use the object lists in max so I’ve never bothered
to make one.
>
> But my main issue is that if I open the patches that have been posted, I only see a jit.window and not the patch itself.
>
> Same problem on Andrew and Wes’s patches. Thought it had something to do with the lines at the top of the text. I’m assuming these refer to where the patcher window appears.
>
> I thought that because I’m on a little powerbook, maybe the patcher window was out of sight. So edited the text so that it’s the same as the patch I posted. Still no joy…..
>
> I’m probably missing something very obvious here…..
>

What are the precise steps you do to take text and turn it into a
patcher? I’m working at 1280×854. This shouldn’t make a difference.
Do you take the text and paste it into a new max patcher? This is the
way you should go. I’ve never had a problem with this technique but
maybe your system doesn’t take to it somehow. If you paste the text
into a new patcher, the patcher won’t be offscreen as it’s right there
where you created it.

best,
wes


February 17, 2006 | 8:34 am

still don’t see them in the right-click context.
but with the list they show up in the new object window.

But…..on the other matter….

I’ve been opening a text file, copying the posted patch text into that and then saving it. Then opening as a patch. Dumbkopf!

This is more like it!

Please excuse my ignorance. Will examine patch and let you know how I get on.

xray.jit.cellcoords looks like the daddy….

Many thanks


February 18, 2006 | 3:39 am

So using matrixoutput on jit.gl.isosurf seems to be spitting out the gl co-ordinates in order. Which is fantastic.

The only thing is that there are rather a lot of them.

The dimension of the matrix seem much bigger than they should be. ie, if the dimensions given to the isosurf object are 80 x 60 x 2, then the resulting ‘matrixoutput’ matrix is

1 x 144000.

Most of this matrix is just zeroes.

My ideal scenario would be to filter this matrixoutput data so that I get a 2d matrix at around the same resolution as what I’m feeding the isosurf object. So if isosurf res is 80 x 60, I get a matrixoutput 1 x 480.

I don’t need the third dimension as I’m only drawing in 2d.

Trying jit.submatrix, etc but no consistent joy yet.

The reason I need to filter the information is that it will eventually be fed as a 2d 1 x 1920 matrix to jit.release @ 25fps to create a 2 channel 48k audio signal.

Sorry for the length of this saga. Here’s an amalgam patch.

#P window setfont "Sans Serif" 9.;
#P flonum 104 204 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P flonum 68 204 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P flonum 32 204 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P window linecount 1;
#P newex 32 235 95 196617 pak position 0. 0. 0.;
#P number 545 393 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P number 505 394 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 506 417 62 196617 pak dim 0 0;
#P flonum 390 618 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 328 650 44 196617 jit.op *;
#P flonum 387 579 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 328 598 43 196617 jit.op +;
#P newex 243 899 185 196617 jit.gl.mesh foo @draw_mode line_strip;
#P user jit.pwindow 456 664 82 62 0 1 0 0 1 0;
#P toggle 492 344 15 0;
#P message 493 376 84 196617 matrixoutput $1;
#P message 493 847 61 196617 1 130650;
#P message 430 847 60 196617 float32;
#P message 367 847 174 196617 12;
#P newex 493 825 60 196617 prepend set;
#P newex 430 825 60 196617 prepend set;
#P newex 367 803 199 196617 route planecount type dim;
#P newex 367 825 60 196617 prepend set;
#P newex 298 751 72 196617 jit.matrixinfo;
#P user jit.fpsgui 59 428 60 196617 0;
#P user jit.pwindow 161 513 82 62 0 1 0 0 1 0;
#P flonum 375 401 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 297 424 63 196617 jit.op @op >;
#B color 5;
#P newex 297 404 66 196617 jit.rgb2luma;
#B color 5;
#P newex 298 445 151 196617 jit.matrix 1 float32 320 240 2;
#B color 5;
#P newex 121 325 75 196617 jit.window foo;
#P toggle 59 300 15 0;
#P newex 59 324 51 196617 qmetro 5;
#P newex 59 349 95 196617 t erase b b;
#P newex 59 401 195 196617 jit.gl.render foo @erase_color 1. 1. 1. 1.;
#P newex 298 479 249 196617 jit.gl.isosurf foo @scale 1.333 -1. 0.1 @dim 80 60 2;
#P flonum 320 322 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P message 320 342 42 196617 rate $1;
#P message 380 322 28 196617 read;
#P newex 297 380 103 196617 jit.qt.movie 320 240;
#B color 5;
#P connect 35 0 5 0;
#P fasten 36 0 35 1 37 227 65 227;
#P fasten 37 0 35 2 73 227 93 227;
#P fasten 38 0 35 3 109 227 121 227;
#P connect 34 0 32 2;
#P connect 33 0 32 1;
#P connect 32 0 4 0;
#P connect 4 0 27 0;
#P connect 4 0 16 0;
#P connect 10 0 4 0;
#P connect 6 0 5 0;
#P connect 29 0 28 1;
#P connect 31 0 30 1;
#P connect 12 0 14 0;
#P connect 12 0 10 0;
#P connect 20 0 23 0;
#P connect 18 2 20 0;
#P connect 25 0 24 0;
#P connect 19 0 22 0;
#P connect 18 1 19 0;
#P connect 17 0 21 0;
#P connect 18 0 17 0;
#P connect 16 0 18 0;
#P connect 13 0 12 1;
#P connect 3 0 2 0;
#P connect 24 0 4 0;
#P connect 11 0 12 0;
#P connect 0 0 11 0;
#P fasten 2 0 0 0 325 369 302 369;
#P fasten 1 0 0 0 385 369 302 369;
#P fasten 6 2 0 0 148 374 302 374;
#P connect 5 0 15 0;
#P fasten 6 1 5 0 106 377 64 377;
#P connect 7 0 6 0;
#P connect 8 0 7 0;
#P window clipboard copycount 39;


February 23, 2006 | 8:10 am

The patch below outputs a single line matrix of about 5-6000 points.

But if I try to reduce it down to my target of a fixed matrix 1920 points, the drawing order gets messed up.

Damn!

I’ve bastardised the cellvalue help file to show what I mean.
Try pressing the adapt switch.

bball works well as an example.

Any tips on maintaining the drawing order or am I trying to square a circle?

#P toggle 508 456 15 0;
#P window setfont "Sans Serif" 9.;
#P window linecount 1;
#P message 484 485 49 196617 adapt $1;
#P newex 405 549 170 196617 jit.matrix sample 3 float32 1 1920;
#P newex 483 605 46 196617 jit.print;
#P newex 405 513 68 196617 jit.transpose;
#P message 183 638 61 196617 5646 1;
#P message 57 634 60 196617 3;
#P newex 183 612 60 196617 prepend set;
#P newex 57 590 199 196617 route planecount type dim;
#P newex 57 612 60 196617 prepend set;
#P newex 57 567 70 196617 jit.matrixinfo;
#B color 5;
#P window linecount 2;
#P comment 195 561 148 196617 outputs the planecount type and dimensions of the input matrix;
#P window linecount 1;
#P newex 54 251 48 196617 loadbang;
#N vpatcher 62 381 370 647;
#P window setfont "Sans Serif" 9.;
#P newex 202 135 33 196617 / -2.;
#P newex 163 135 27 196617 / 2.;
#P newex 163 156 61 196617 pak 0. 0. 0.;
#P newex 202 114 31 196617 r glh;
#P newex 163 114 34 196617 r glw;
#P newex 38 182 124 196617 jit.op @op – @val 0. 0. 0.;
#P newex 142 83 61 196617 pak 0. 0. 0.;
#P window linecount 1;
#P newex 187 56 45 196617 / -240.;
#P window linecount 0;
#P newex 142 56 40 196617 / 320.;
#P window linecount 1;
#P newex 187 35 31 196617 r glh;
#P newex 142 35 34 196617 r glw;
#P window linecount 0;
#P newex 38 104 114 196617 jit.op @op * @val 1. 1.;
#P outlet 38 208 15 0;
#P inlet 38 69 15 0;
#P connect 0 0 2 0;
#P connect 2 0 8 0;
#P connect 8 0 1 0;
#P connect 3 0 5 0;
#P connect 5 0 7 0;
#P connect 7 0 2 1;
#P fasten 11 0 8 1 168 176 157 176;
#P connect 9 0 12 0;
#P connect 12 0 11 0;
#P fasten 6 0 7 1 192 78 172 78;
#P connect 4 0 6 0;
#P fasten 13 0 11 1 207 154 193 154;
#P connect 10 0 13 0;
#P pop;
#P newobj 405 463 58 196617 p Pixel2GL;
#P newex 405 313 142 196617 jit.matrix 1 float32 320 240;
#P newex 405 334 40 196617 t b b l;
#P newex 405 402 53 196617 jit.pack 3;
#P newex 426 362 94 196617 jit.matrix Y-coord;
#P newex 405 382 94 196617 jit.matrix X-coord;
#P button 54 273 15 0;
#P newex 80 334 94 196617 jit.matrix Y-coord;
#P newex 54 354 94 196617 jit.matrix X-coord;
#P newex 54 313 63 196617 jit.unpack 2;
#P newex 54 292 283 196617 jit.gencoord 2 float32 320 240 @scale 320 240 @offset 0 0;
#P newex 388 267 27 196617 t l l;
#P newex 405 429 148 196617 xray.jit.contourmap @levels 1;
#P newex 405 292 66 196617 jit.rgb2luma;
#P message 451 224 28 196617 read;
#P flonum 430 203 35 9 0.5 0 1 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P toggle 388 203 15 0;
#P newex 388 223 52 196617 metro 40;
#P newex 388 247 103 196617 jit.qt.movie 320 240;
#P newex 15 42 55 196617 delay 100;
#P newex 15 20 48 196617 loadbang;
#P window setfont "Sans Serif" 10.;
#P comment 260 164 38 196618 height;
#B frgb 178 180 167;
#P comment 105 164 32 196618 width;
#B frgb 178 180 167;
#P window setfont "Sans Serif" 9.;
#P newex 423 642 258 196617 jit.gl.mesh cellvalue @draw_mode lines @color 1 1 1 1;
#P newex 201 183 31 196617 s glh;
#P newex 138 183 34 196617 s glw;
#P flonum 138 164 59 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P flonum 201 164 59 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P window linecount 3;
#P message 15 65 72 196617 getdest_dim , getcamera , getlens_angle;
#P window linecount 1;
#N vpatcher 385 97 759 364;
#P outlet 131 150 15 0;
#P window setfont "Sans Serif" 9.;
#P window linecount 0;
#P newex 131 128 29 196617 * 1.;
#P window linecount 1;
#P message 270 77 20 196617 $2;
#P message 248 77 20 196617 $1;
#P newex 248 95 32 196617 / 1.;
#P message 101 70 20 196617 $3;
#P newex 50 92 184 196617 expr $f2*2*tan($f1/2*3.1415/180);
#P newex 50 50 164 196617 route lens_angle camera dest_dim;
#P inlet 50 30 15 0;
#P outlet 166 152 15 0;
#P connect 1 0 2 0;
#P connect 2 0 3 0;
#P connect 2 1 4 0;
#P fasten 3 0 8 0 55 115 136 115;
#P connect 8 0 9 0;
#P fasten 5 0 8 1 253 118 155 118;
#P fasten 3 0 0 0 55 115 171 115;
#P fasten 4 0 3 1 106 88 229 88;
#P fasten 2 2 6 0 157 73 253 73;
#P connect 6 0 5 0;
#P fasten 2 2 7 0 157 73 275 73;
#P connect 7 0 5 1;
#P pop;
#P newobj 194 139 76 196617 p CalcGLHeight;
#P newex 198 66 173 196617 jit.window cellvalue @depthbuffer 1;
#P message 156 66 34 196617 reset;
#P newex 156 87 208 196617 jit.gl.handle cellvalue @inherit_transform 1;
#P toggle 95 47 15 0;
#P newex 95 66 57 196617 qmetro 60;
#P newex 95 87 50 196617 t b erase;
#P newex 95 119 108 196617 jit.gl.render cellvalue;
#P connect 24 0 39 0;
#P connect 24 0 36 0;
#P connect 16 0 17 0;
#P connect 17 0 8 0;
#P connect 37 0 30 0;
#P connect 30 0 26 0;
#P connect 26 0 27 0;
#P connect 27 0 28 0;
#P connect 27 1 29 0;
#P fasten 16 0 3 0 20 39 100 39;
#P connect 3 0 2 0;
#P connect 2 0 1 0;
#P fasten 1 1 0 0 140 115 100 115;
#P fasten 1 0 0 0 100 111 100 111;
#P fasten 8 0 0 0 20 115 100 115;
#P fasten 4 0 0 0 161 115 100 115;
#P fasten 7 0 10 0 199 160 143 160;
#P connect 10 0 11 0;
#P connect 5 0 4 0;
#P connect 0 1 7 0;
#P fasten 7 1 9 0 265 160 206 160;
#P connect 9 0 12 0;
#P connect 20 0 19 0;
#P fasten 22 0 18 0 456 243 393 243;
#P fasten 19 0 18 0 393 246 393 246;
#P connect 18 0 25 0;
#P connect 25 1 23 0;
#P connect 23 0 35 0;
#P connect 35 0 34 0;
#P connect 34 0 31 0;
#P connect 31 0 33 0;
#P connect 33 0 24 0;
#P connect 36 0 45 0;
#P connect 45 0 47 0;
#P connect 48 0 47 0;
#P connect 47 0 13 0;
#P fasten 34 1 32 0 425 356 431 356;
#P connect 32 0 33 1;
#P connect 21 0 19 1;
#P connect 34 2 33 2;
#P connect 49 0 48 0;
#P connect 39 0 41 0;
#P connect 41 0 40 0;
#P connect 40 0 43 0;
#P connect 41 2 42 0;
#P connect 42 0 44 0;
#P window clipboard copycount 50;


February 23, 2006 | 8:33 am

ok,
You can get less point and better efficiency by using a smaller
matrix. I set the dims to 80 x 60 and the contours basically look the
same. About the contouring algorithm. It doesn’t follow curves at
all. It works by scanning through a matrix of values one row after
the other. If you imagine the video image in grayscale format as a
heightmap with bright values as peaks and black values as valleys, the
contouring algorithm is looking for the location of particular
heights. Obviously, this is going to be between pixels for the most
part. So, when the algorithm encounters a change in value from one
pixel to another that passes through the level it is looking for, it
creates a line at that location. The result of this is that the
output is sets of pairs of points without regard for order. When you
force the output into a fixed size matrix, you are mucking up the
carfully chosen pairs of points and getting bad connections between
lines. If you absolutely must have a fixed number of points, I’m
afraid this approach will only cause many headaches. If you can
handle a certain number of points below a certain maximum, this
approach can work.

I would suggest playing with the dimensions of the matrix you apply
the contouring algorithm to as that will determine for the most part
about how many points you get back. then,I would add a safety that
clips the size of the matrix to a certain value.

If you absolutely must have the points in order, I’m afraid you’re out
of luck as both the contourmap and the isolevel algorithms say nothing
about connectivity. This requires quite a bit of extra logic that is
a pain in th arse to implement, which is why no one has done it for a
jitter object so far (as far as I know). I did a rudimentary
connectivity-based object a few months ago, and it was really
difficult to say the least.

best,
wes


February 24, 2006 | 1:35 am

Right. Got it. The lines just appear to be joined up. But they aren’t.

I spoke to a technological friend about this issue. Here’s how he thought it could be done.

1) Make the silhouette completely black and white. (object is white)

2) Scan the matrix from the top for the first pixel containing white. Record its position.

3) Make this pixel the centre of a 3×3 region. Search the region clockwise for the next white pixel. If you find one, check that it’s not one that you’ve already recorded.

4) If you can’t find a white pixel, expand the region to 5×5, 7×7 until you do. If you’ve hit the edge of frame, move along the edge of frame until you find another white pixel.

5) Record the newly found pixel and make it the centre of a 3×3 region.

6) Repeat the process until you get back to the first pixel you started with.

Obviously this means you’ll only get a solid shape around one object, but this would be sufficient for my needs.

So, great in theory. But obviously not too easy.

Does it sound far too difficult to implement this with real-time video?

Are there any existing objects or code that already do some of this?

Looks like something to do in js or code? Any ideas of what resources it would need to make something like this work?

If it was reasonably economical,I would be more than happy to commission someone with superior coding skills. I have realised that coding is not my thing.


November 13, 2011 | 8:58 pm

I’m reviving this thread as there was a lot of good work in it that pertains exactly to what i’m trying to do.

Lyallmarcus, did you ever get this going as you wished?

I’ve been struggling the last few days trying to find a way to output the contour of in a sequential order (in order of connectedness).

as you mentioned in your last post, you have to implement an algorithm: find the first "on" pixel from the edge of the matrix, and then follow its connected neighbors until you get to the end of the line.

but i see no way of doing this with the objects i know of.


January 24, 2012 | 11:54 pm

A variant on this is the marching squares algorithm (marching cubes for 3D shapes).

See http://en.wikipedia.org/wiki/Marching_squares


Viewing 28 posts - 1 through 28 (of 28 total)