First, some small preparations:
In [2]:
load 'viewmat'
load 'bmp'
VISIBLE_jviewmat_ =: 0
Create the sobel filter. The second filter is just a transposed first filter.
In [3]:
sobel1 =: 3 3 $ 1 0 _1 2 0 _2 1 0 _1
sobel2 =: |: sobel1
sobel1 ; sobel2
In [4]:
image =: readbmp <'image_mini.bmp'
viewrgb image
Let's take a look at first few elements of this file:
In [5]:
4 {. 4{."1 image
...this doesn't look familiar at all! That's because J read all three RGB values as a single integer. You could describe this with a formula:
number = (r^3) + (g^2) + (b^1)
Thankfully, retriving them is easy:
In [6]:
rgbimage =: 256 256 256 #:"1 0 image
4 {. 4 {."1 <"1 rgbimage
Okay, now that we got RGB values, let's get rid of them. Colors aren't that important is basic edge detection, so we'll convert the image to grayscale. I go the easy way and just calculate the average of these three values.
In [7]:
greyimage =: 3 %~ (+/"1) rgbimage
If I wanted to see this greyscale image right now, I have to convert it back to a format similar to the original one. Here I just floor the numbers, make them in to RGB triples of the same values, convert into single numbers and pass to viewrgb
function.
In [8]:
viewrgb 256 #. 3 #"0 <. greyimage
Okay, now let's get to the actual algorithm. The first thing I do is cutting the matrix into 3x3 overlapping slices.
In [9]:
cells =: 3 3 ,.;._3 greyimage
As you can see below, they always overlap - these are basically all 3x3 areas in the image.
In [10]:
3 {. 3 {."1 <"2 <. cells
Now let's just piecewise multiply each cell with the sobel matrix, then sum all nine resulting values - and we get the resulting pixel value. Repeat for the second matrix.
In [11]:
partial1 =: +/"1 +/"1 sobel1 *"2 cells
partial2 =: +/"1 +/"1 sobel2 *"2 cells
The last thing we need to do is to combine these two images. I'll use the simple formula pixel = sqrt(pixel1^2 + pixel2 ^2)
. Finally I'll make sure that no pixel is above 255 by capping theis values.
In [12]:
combine =: [: %: *:@[ + *:@]
limit =: 255 <. ]
In [13]:
newimage =: limit partial1 combine partial2
Finally, let's display the result, like I did above.
In [14]:
viewrgb 256 #. 3 #"0 <. newimage