Iterating over jit.matrix
What I’m trying to do is very simple. It takes three lines in matlab. But I can’t figure out how to do it in max.
I have a jit.matrix that holds a black and white picture. What I want to do is run over the rows of the matrix, from right to left, and when I hit a non-white cell, add the column coordinate of that cell to a list.
(The picture is a profile of a face, where the face is black and background white, and I’m trying to find the outline of the face).
How can I do this?
Or the brute-force way, using [uzi] and the "getcell" message, holding the cell coordinates, and if the value is 0, bang the coordinates into your list. This "nested for-loop-approach" will be a lot slower than [jit.iter] though.
How exactly would you do it with iter? I need to jump to the next line every time I encounter a black pixel.
You’d probably need to use the getcell approach if you have to conditionally jump to the next line.
Another idea is [jit.spill] and you can find the first black (0) element by using [zl filter 0] on the list. This will give you all the black pixels in the row and their indices, so you can keep additional ones if you want. [jit.spill] will be a lot faster than getcell too.
There’s no good solution for doing this kind of thing with standard Jitter objects. I wrote an object years ago to solve this exact problem. It’s called xray.jit.cellcoords. You can download the objects here:
Thanks! This looks really helpful. I’m having trouble understanding the xray.jit.cellcoords help file, though. What exactly does this object do?
It gives you the cell coordinates of all cells of the input matrix that are logic 1 (1 or 255 if it’s char). For example a 1-plane float32 matrix that looks like
[0 1 0]
[1 0 0]
[0 0 1]
outputs a matrix:
[(1, 0), (0, 1), (2, 2)]
Okay, so it outputs a matrix of tuples? Or is it a two plane matrix?
I’m not sure I see how I could use such a matrix to find just the first white cell in each row…
Maybe the cellminmaxx object would be better? Can it be used to scan the matrix horizontally and find the first nonzero cell value in each row?
If the resolution of the image is not too big I would do that by converting the matrix into a list using jit.spill. Then you have plenty of ways to get the indices corresponding to non-white cells, using the functions from the zl family, that also works for long lists, i.e. big images. But if the image has many pixels, using an external is the way to go.
I think you could simply use [jit.iter] and [togedge] to detect zero/non-zero transitions.
Another useful object if you’re trying to get a silhouette is xray.jit.distance. You can pass in a binary mask to it and then threshold the result to get just the outline pixels. If you then piped that into xray.jit.cellcoords, you’d have a matrix with all of the outline pixel cell coordinates.
That’s exactly what I need! Sorry for the n00bness but what exactly do you mean by "pass in a binary mask and then threshold the result"? Thanks for the help!
This patch that you (Wesley) posted in this thread http://www.cycling74.com/forums/topic.php?id=547 looks very similar to what I’m trying to do. I just need to take it one more step and get a vector with the cell coordinates of the outline pixels. If you could explain how to do that using xray.jit.distance I would be over the moon :)
Here’s a picture as an example of what I’m going for. With Wesley’s patch I can turn the girl’s face into black and white outline. But I need to get rid of the white pixels inside the face (the eyes, for example), if I’m going to use jit.cellcoords to extract just the pixels that make up the silhouette.
Here’s what I was thinking:
----------begin_max5_patcher---------- 1708.3oc6bstbahCE92NOELL6Oc8pKbcmo6z84XmcxH.EaRw.UfSR2N8ceER xINo1xJIvAuSamVrgPfy46b66bDzuc0B+rlG3c9d+g2e6sXw2tZwB0gFNvBy 9K72xdHuh0oNM+Z98MY25uT+i54OzqN7sk8qZZ89j7ee7ide5NVkGd+IUuaa yt9Jdu5JPLG8ll59tx+kObrzUHyQ0mX+Wa4ZgZ3Be8VVun7A+kd99d+i4DaY 84aJqWesfm2qO2.BZU3RORJRd47RCG1hiWgd72orPIqR4+CAI9GHG0rsp6m+ eIJYUGH2k0OJ1CG66Wc0vlkuOrJ+tUCvUQYEqm6NHgIiBJQoQZfIX3iH0NRf 63nT7qDkvuAT5lpF40XbvA40h0O.AYr501cVPJ8OAOrMDYEEhNOJzxDxi2yE WyqYYUpy.MVHzf2R68k0EM2aGl9A737wLwoFUWF4PIZbH3T.AYzL5mOMxepy hHErzXnyjPw5XDJQ8AJ1ZpD77kJ4AA6qljIc8r574HcxS9LxjtDaARzT.RmL gAKzHjNagx63bQKzjQSmx1022Teb0AeJ04ro.oITkBnqDPrmCDAXn+uaHPDg 79fbC37HL12DcX+95kGGXlwf+ikrjBMXgMfEFoSUZErHW.YJy4UU4MMhhNIx sSpmME7YfqZfJniFf09XI1fMJ.oMs3istZ0Vd2FusLQ9NIpUHX2qgspxZ90c REtEd7S4nEDXnuDXsB8qD+RGW7SqRdAd4aXBUVMLA7jZFFMo5OHo1vqPvY8m sNuopQnEUzpjH4ehWdzugOPleWf2I5UXyfs64RSLJLIY4Q+1gRizNzkyLb+W kdZaQRrpva.RYEnVaTct683mZ6j1zDnqsY2NE+K6zrYmhSic1NkLy1oSTmnk 8YoNp+qcd9NZMrVLHN0T8T8gtqlSAXu1d1niHnH3s75Bub4cUvfCVhUjxRrB KXD.EI6aVuth+J66qrt2tVFpBPnHcbxiaOpVhAa.W2z1sdW4nPK5rjgRzrgB ozm7+Gl0yQg.x7x99KYrpJXfk3PcubgJ1zATq9+fzTxtsYbwbVTaHXZVndfT 4fHoNPQDGbYVSSd+DMdmpUmWYh6yNMq8NuT8D8siXgy2fH58x7jUy53dYGGX nuAfQ5hptlNszG6QpjPGPpn4M6mdPt6G8Pnji2vbW8HIiyDa1Cd1wKMefvHc Sy1oKgim8g0Hjbl3BClAILkbvzwwH6vTx7BSYcMhdnmASHUOocck0.qy7Cm9 qgvLoUXMqpGIzgJrDzLWgcKuqisl+iES1HFlL6ugm9li1iW5ELNjXqsAxLup HhlrbQSWG3CYU6KoWRzHqyjlP.ZsPgruJhteJMoU6sUQfn+gSE1fAXFKlDK3 vGaixR7R..wK+Tmr2PZKIwgj8g+ZTtylghPic2PEcgVUNSTtdSes7mBSk4Hy itgB5hQVyzDCPllSgK4xaorK0dPPEimjAUhvVQkj4kuRlHuoiA9ZnqvGMLY3 ycpHMGZF4f7BJrVlHHEgSiF9Fx7sWjfZx5taWcKK+yGGOCeO3o664.xqWfgH qOwLTz+uej4z7dBb7IlCO4L+DbVwzm6wP8GoeZHSrk5gRlwDxc8Ms.Teh9L3 vJSXJcVgC1oFJz31IM5.7fZsxDEhNCljkYD+ziWu80XjFdArHEvrFEZzPuzN AVGO.MZdYj7k9Uaatqjqm1d.7OtZ5QsqcbPVWIRZLfjSTmg+vy83KdqoT5vv weNd20rSjuW+2+hG48zMpf20WVy5KapO3jnO6b1TVTvqOLXnnraH9PgAniZ3 GUwY389.H4Y3UD37xSBb3SrKlqT3vGYjnG9b3CFN7IxE6E9YB8jJOXWjm3KK 6EEN+YpCvCbdOtDrO7fVAj33RtP3B0icTZfIvJxQog.hzD5fzPfyTEfbQdfK H2EWmP3DGW7cnmKm71xh1FYSGc6ahZ3MVEa5d5ocd51LdxuKdauPImT7LXRv yTEFZlVA5wclB.kNEJP.ENEfLAJPLfxuKrjHzKKVRD3RfRbgXBENhIjjwnd2 K72HAQp+6xv7RtSebmIvgiDOAJ.NJENEvkZXD33wSbhADb84PbolDI5U5gFk nxBpevBM9qp8lBKrSZP36QCLNrSlFPtnXgRbpHCfxiSjzgq4Wm3P.m3fcICG NAV4AegIOjyIOv4NicoB.FNNbXWxepDZXFXA1oQcAWWaXrq3CPxC5BKd2kA2 9FkF8p1vZauiK5LWRkf3ukcqdgghVp1srVuq5J5K32Ut+7CtZ3p88q9O.aST LnB -----------end_max5_patcher-----------
You’ll probably need to use some cv.jit objects to fill in the area you want silhouetted. The basic idea is to color everything you want inside the shape white. You can then use jit.robcross or whatever to create the outline.
it would be great to be able to do the equivalent of [zl sub] with an object similar to jit.spill – gets all coordinates that are x in a normal max list, unlike jit.xray.cellcoord.
for my money [zl sub] is a great way to detect positions, and being able to apply this directly would be handy while reducing the number of big non-jitter lists flying around.
I’m sorry to be so slow but I’m not sure I understand what the patch you posted does. I’m seeing three outputs: one that looks like edge detection of the image, one in grayscale and then the third is just black.
If I understand correctly what you’re suggesting is to somehow fill in the face so that it will be all white and the use detection to extract just the silhouette line. That sounds great but I have no experience at all with the cv.jit objects…are there any in particular that could help me do that?
Thanks so much