I spent a good part of the summer playing with coding image processing algorithms in Julia. I have to say I am impressed. Not only because of the speed, because it is impressive. Not only because it is not C, because I mean, I do like C, but it’s not nice for dealing with 2D arrays. No, largely because it is a pleasure to code. It’s SO much fun, I have decided to build an nice little image processing library, which I will later post to GitHub (maybe).
Many image processing algorithms involve a lot of processing of blocks of information from arrays. this has always been challenging in traditional languages such as C because of the lack of slicing infrastructure. Like Fortran, and Matlab, Julia performs this in a trivial manner. Kernels (or masks) can be easily defined:
kernel = [-1 0 1; -4 0 4; -1 0 1]
Now applying this to a 3×3 neighbourhood over a whole image is easy.
dx,dy = size(img) newI = zeros(Int,dx,dy) for i = 2:dx-1, j = 2:dy-1 # Extract the 3x3 block from the image imgBlk = img[i-1:i+1,j-1:j+1] # Apply the kernel newI[i,j] = sum(imgBlk .* kernel) end
From a speed perspective this code is obviously slightly slower than C, but Julia more than makes up for it in clarity, and brevity.
The one downside is again recursion. There are a couple of image processing algorithms out there that use recursion, flood-fill is one of them (see previous post). The other one I came across is related to Canny edge-detection. The last step in the algorithm applies hysteresis thresholding, which uses recursion to handle spatial connectivity, i.e. find pixels that should belong to an edge. The problem of course lies in the fact that with some images, this may require excessive use of stack space, which in C is not a problem, but with Julia it is. The solution is simple however – just use a stack to simulate recursion (as stack functions are built-in to Julia, there is not even a requirement to build a stack module).