[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:
ftp://urpla.net/cap00013.jpg
ftp://urpla.net/cap00013-0.jpg
ftp://urpla.net/cap00428.jpg
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
continue
else:
lx, dv = 0, 0
v = cmppixel(hsv1, hsv2)
if v >= minvdev:
while v >= minvdev:
px2 += 1
if px2 >= width:
break
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,
Pete
More information about the Image-SIG
mailing list