[Image-SIG] PIL 'special' edge detection problem

Hans-Peter Jansen hpj at urpla.net
Tue Sep 16 01:34:20 CEST 2008

Dear PIL-Pythonistas,

I'm trying to solve a problem with PIL which is basically related to edge 
detection, but please bear with me, since I'm pretty dump, when it comes to 
image processing apart from the very basics..

All the mess starts with a camera (Canon PowerShot 100 SX), that often 
creates erroneous images in certain twilight conditions. The ugliest failure 
is one, where parts of the image are wrapped, and color in that area is mixed 
up in some way. Hard to explain, here are some (resized) examples:

Ugly, isn't it. While it would be best to exchange the camera with a model, 
that doesn't suffer from these problems, that is not an option at this point.

Now, I try to detect these folds. My 'solution' misses any sophisticated 
image processing algorithm, I simply compare one pixel with the one below,
convert it to HSV (with ranges: 0..255, 0..100, 0..100), combine h and v 
deviations into a value, and try to find horizontal runs of patterns with a 
high enough value.

While the below code does it's job in some way, it's way too slow to be 
really useful, given the the original bitmap is 3264x2448 and that the camera 
is controlled by a small VIA C7 based system, which is unable to run this code 
even nearly fast enough :-(.

Does some kind soul know some better way to solve my issue (propably python
based). What I need is some special kind of horizontal edge detection, but 
where false positives are highly undesired. I know, that it should be possible 
with numpy, but maybe PIL filters may fit the job, too...

Pointers to some comprehensible theory would also be great.

Here's my code (note, that it won't work with the example images, since they
are resized, and the thresholds doesn't match anymore). The full images are
available in a subdir called fullres in the location above, as is the full 
script chkimage.py, but remember it's a test script, and it contains lots of 
unused stuff ATM..

    def chkwrappedimage(self, ipixel, width, height, fname):
        xstep = 20
        minvdev = 80
        mincnt = 12
        foldtres = 80000

        def getpixel(x, y):
            rgb = ipixel[x, y]
            hsv = RGB2HSV(*rgb)
            return rgb, hsv

        def cmppixel(hsv1, hsv2):
            h1, h2 = hsv1[0], hsv2[0]
            h = abs(h2 - h1)
            if h > 180:
                h = 360 - h
            v = abs(hsv1[2] - hsv2[2])
            return h + v

        def chkimgfold(x1, x2, xstep, y1, y2):
            foldd = {}
            for x in range(x1, x2, xstep):
                lastpix = None
                for y in range(y1, y2):
                    rgb, hsv = getpixel(x, y)
                    if lastpix != None:
                        px1, py1, rgb1, hsv1 = lastpix
                        px2, py2, rgb2, hsv2 = x, y, rgb, hsv

                        if (py1, py2) in foldd:
                            mx, lx, dv = foldd[(py1, py2)]
                            if mx >= px2:
                                lastpix = x, y, rgb, hsv
                            lx, dv = 0, 0
                        v = cmppixel(hsv1, hsv2)
                        if v >= minvdev:
                            while v >= minvdev:
                                px2 += 1
                                if px2 >= width:
                                px1 = px2
                                rgb1, hsv1 = getpixel(px1, py1)
                                rgb2, hsv2 = getpixel(px2, py2)
                                v = cmppixel(hsv1, hsv2)
                                if v >= minvdev:
                                    dv += v
                            n = px2 - x
                            if n >= mincnt:
                                foldd[(py1, py2)] = px2, lx + n, dv
                    lastpix = x, y, rgb, hsv
            return foldd

        foldd = chkimgfold(0, width, xstep, 0, height)
        r = []
        for k, d in foldd.items():
            mx, lx, dv = d
            r.append((int(dv), k, lx))
        r.sort(reverse = True)

        if r:
            dv, xy, lx = r[0]
            if dv >= foldtres:
                return 'wrappedimage: %s folded at %s: value: %s (lx: %s)' % (
			fname, xy, dv, lx)

Any hints/ideas to solve this issue in a sane way are highly appreciated.

Thanks in advance,

More information about the Image-SIG mailing list