Edge Detection in Python
Posted on July 13th, 2008 in Image Processing, Python |
I’ve been reading up on digital image processing and wanted to have a go at implementing a Sobel edge detector. I’m fairly familiar with PIL, so I decided to implement the algorithm in Python. Python is not by any means and ideal language for digital image processing; it is far too slow for most things, but for the time being the speed doesn’t matter. Anyway, here is the basic implementation:
def sobel(img): if img.mode != "RGB": img = img.convert("RGB") out_image = Image.new(img.mode, img.size, None) imgdata = img.load() outdata = out_image.load() gx = [[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]] gy = [[-1, -2, -1], [0, 0, 0], [1, 2, 1]] for row in xrange(1, img.size[0]-1): for col in xrange(1, img.size[1]-1): pixel_gx = pixel_gy = 0 pxval = sum(imgdata[row,col])/3 for i in range(-1, 2): for j in range(-1, 2): val = sum(imgdata[row+i,col+j])/3 pixel_gx += gx[i+1][j+1] * val pixel_gy += gy[i+1][j+1] * val newpixel = math.sqrt(pixel_gx * pixel_gx + pixel_gy * pixel_gy) newpixel = 255 - int(newpixel) outdata[row, col] = (newpixel, newpixel, newpixel) return out_image
The results are surprisingly good:

2 Responses
If you use numpy for this sort of thing, and make sure that you compress all of the big loops down to linear algebra that happens inside numpy, and especially if you add psyco on top, you can actually get quite good results out of python.
Also, you can use pyrex and/or ctypes for anything on which this doesn’t work.
Footnote: euclidian distance is a built-in function:
>>> import math
>>> help(math.hypot)
Help on built-in function hypot in module math:
hypot(…)
hypot(x,y)
Return the Euclidean distance, sqrt(x*x + y*y).
(and yes, even if “heavy” image processing is somewhat outside the scope of PIL, a more flexible filtering machinery is on my TODO list…)