I'd like to introduce you to ~:/\

~:/\ is an illustration of one of the things I really like about J. It is
equivalent to 2 | +/\ ] but without the possibility of overflow. And it
turns out to be really handy when reasoning about bit operations.

One way of describing it is as a slightly flawed self inverting edge
detection operation.

   ~:/\ 0 0 1 0 0 0 1 0 0

0 0 1 1 1 1 0 0 0

~:/\ ~:/\ 0 0 1 0 0 0 1 0 0

0 0 1 0 1 0 0 0 0


Notice how the opening 0 1 transition stays anchored in place, but the
closing 1 0 transition drifts just a little bit.


Now, if you use Henry's E. suggestion and look for 0 1 1 1 1 1 1 1 1 1 1 E.
and 1 1 1 1 1 1 1 1 1 1 0 E. you will have bits marking the beginning of
your lines and the endings of your lines. Use +. to combine these bit masks
and you have a perfect candidate for ~:/\


Or, almost. You will need to add a leading zero to the beginning of each
line if you want to detect lines on columns which are all 1s (and then drop
that leading zero, later).


For rows, I'd probably just transpose the array and use the version of the
code designed for columns. (But you could try doing all the operations at
rank 1, also.)


Except that's still not quite right. Consider what happens if you encounter
0 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 -- here, you have the same
bit marking an opening and a closing position. So, instead of combining the
E. results using +. I think you should combine them using ~: -- this will
do the right thing both for isolated marking bits and for conflicting
marking bits, assuming you are OK with "almost complete lines" being
classified as "solid".


Good enough?


Thanks,


-- 

Raul



On Wed, Feb 19, 2014 at 9:43 AM, Joe Bogner <[email protected]> wrote:

> On Wed, Feb 19, 2014 at 7:25 AM, Henry Rich <[email protected]> wrote:
>
> > Look at
> >
> > (1 10$0) E. image
> >
> > or
> >
> > (10 $ 0) E. line
> >
> >
> Thanks Henry, that worked well. I have a version that seems to work now
> (albeit clunky)
>
> ]lines=: 4 10 $ (0 0), (5 $ 1), (3 $ 0),(5 $ 1), (0 0 0), (1 1), (10 $ 1)
> lineStarts=:(1 5$1) E. lines
>
> markPixel=: 3 : 0
> shift1=:0,.(}:"1 y) NB. shift the array by 1 to the right
> shift1Marks=: shift1 = 1
> shift1Marks+. y
> )
>
> s1=:markPixel lineStarts
> s2=:markPixel s1
> s3=:markPixel s2
> s4=:markPixel s3
>
> viewmat (s4=0)
> viewmat (lines=0)
>
> Basically, I mark the first pixel of the line (having 5 consecutive 1s) and
> then shift the array 4 more times and mark each one that is a 1 and OR it
> with the input array.
>
> I'm happy to take any feedback from anyone on how to improve it. I know I
> can make makePixel a 1 liner...
>
> markPixel=: 3 : 0
> y +. (0,.(}:"1 y) = 1)
> )
>
> NB. from 13 :
> markPixel =: ] +. 0 ,. 1 = }:"1
>
> I'm more interested in how to avoid the shifting 5 times. The problem is
> that I don't know of anything that can look backwards to match, so I think
> I need to shift forward. Or, I can use my earlier approach of marking the
> last pixel of the line and then look forward, which shouldn't require
> shifts.
> ----------------------------------------------------------------------
> For information about J forums see http://www.jsoftware.com/forums.htm
>
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm

Reply via email to