Programming Forums
User Name Password Register
 

RSS Feed
FORUM INDEX | TODAY'S POSTS | UNANSWERED THREADS | ADVANCED SEARCH

Reply
 
Thread Tools Display Modes
Old Jul 11th, 2006, 2:47 PM   #21
DaWei
Resident Grouch
 
DaWei's Avatar
 
Join Date: Jun 2005
Posts: 6,453
Rep Power: 10 DaWei is on a distinguished road
Just to let you know: this is abominably slow, about 5 seconds for 128x128. (I've downloaded Psyco, but not applied it, yet.) Admittedly, much of that is because of the image objects available in the Python port of wxWidgets. As mentioned earlier, there's not direct access to data on a pixel-by-pixel basis. The procedure is this:

1. For each pixel in the image (other than edge pixels, which are set to black), get a 3x3 sub image.

2. Get the data (pixels) associated with the image. These come in a string, which obviates the necessity of flattening.

3. Remove g and b components, using only the red (it's a grayscale image)

3. Convert the characters to ordinals.

4. Approximate a gradient measurement with Sobel x and y grids (which are now flat, to begin with). This includes applying a gain factor (currently 1), taking the absolute value of negative pixels, and limiting the value to 255.

5. Convert back to characters and replicate for the g and b components.

6. Construct a new wxImage using the string.

The inset on the image shows the output from the old C++ version, which is essentially identical to what one gets with "Find all edges" in Paintshop Pro. I'm not sure, yet, why it's different from the new version. The processing algorithm is identical.
Attached Images
File Type: jpg Transform.jpg (63.8 KB, 93 views)
__________________
Abstraction doesn't make it impossible to write bad code; it makes it possible to write superior code.
Contributor's Corner: Grumpy on C++ Exceptions DaWei on Pointers
DaWei is offline   Reply With Quote
Old Jul 11th, 2006, 3:13 PM   #22
Arevos
Programming Guru
 
Arevos's Avatar
 
Join Date: Aug 2005
Location: England
Posts: 1,499
Rep Power: 5 Arevos is on a distinguished road
Quote:
Originally Posted by DaWei
Just to let you know: this is abominably slow, about 5 seconds for 128x128. (I've downloaded Psyco, but not applied it, yet.) Admittedly, much of that is because of the image objects available in the Python port of wxWidgets. As mentioned earlier, there's not direct access to data on a pixel-by-pixel basis.
Have you considered using PIL to handle the imagines? Perhaps something like:
import Image
import wx

image = Image.open("foobar.png")
width, height = image.size

wx.Image(width, height, image.tostring())
PIL is a library designed for image manipulation, so it may be faster/more convinient to use that. I haven't used it extensively, however, so I'm not sure.

I believe it also has some image filters, though I suspect using a prewritten filter wouldn't teach you much

Your application looks pretty good, though. Unfortunately, I know very little about image manipulation, so I couldn't hazard a guess as to why it isn't outputting the same results as your equivalent C++ program.
Arevos is offline   Reply With Quote
Old Jul 11th, 2006, 3:42 PM   #23
DaWei
Resident Grouch
 
DaWei's Avatar
 
Join Date: Jun 2005
Posts: 6,453
Rep Power: 10 DaWei is on a distinguished road
LOL! I just downloaded PIL. First thing in the tutorial is an example, "open (lena.ppm)". Lena is quite popular in image processing circles, and is, in fact, the lady in the above illustration.
__________________
Abstraction doesn't make it impossible to write bad code; it makes it possible to write superior code.
Contributor's Corner: Grumpy on C++ Exceptions DaWei on Pointers
DaWei is offline   Reply With Quote
Old Jul 11th, 2006, 5:22 PM   #24
Sane
Programming Guru
 
Sane's Avatar
 
Join Date: Apr 2005
Posts: 1,827
Rep Power: 5 Sane will become famous soon enough
@DaWei, your intended result almost looks like it could be shifted and overlayed 1 or 2 pixel(s) to the right, and end up looking like what your application outputs.

Perhaps you missed something simple and are using your indexes incorrectly. I think some libraries also consider the first pixel the zero'eth, and some the first.

Things to consider.
Sane is offline   Reply With Quote
Old Jul 11th, 2006, 7:33 PM   #25
DaWei
Resident Grouch
 
DaWei's Avatar
 
Join Date: Jun 2005
Posts: 6,453
Rep Power: 10 DaWei is on a distinguished road
It hasn't anything to do with position. It's the grayscale. Examination of the histogram shows a dark shift. It's possible I normalized the old image before saving it; I haven't added that transform in this new code.

The PIL offers several advantages. There are a number of transforms/filters available that I've always written myself. It also allows me direct access to the pixels. The GetData function returns a list of numbers, rather than a string of characters, so that precludes having to make a conversion on the way in and another on the way out. I had to import ImageWin to get Windows bitmap/display capabilities. It wants an HDC, whereas wxWidgets encapsulates that as an object. Fortunately, one of the object's methods returns the HDC. As soon as I've rewritten some more code, I'll make a comment on the (subjective) timing.
__________________
Abstraction doesn't make it impossible to write bad code; it makes it possible to write superior code.
Contributor's Corner: Grumpy on C++ Exceptions DaWei on Pointers
DaWei is offline   Reply With Quote
Old Jul 12th, 2006, 11:57 AM   #26
DaWei
Resident Grouch
 
DaWei's Avatar
 
Join Date: Jun 2005
Posts: 6,453
Rep Power: 10 DaWei is on a distinguished road
In case you're interested. Treat the times as relative, as the transform takes about 2 seconds. This is 2 to 2.5 times as fast as working with the wxWidget image (because of the lack of direct access and the conversions).

Note that the gradient calculation is about 20 to 30 percent of the time; the rest is spent in the image library functions. The gradient calculation is made using flat lists. The code is:
    def gradient (self, map, gain):
        a = b = 0
        for i in range (9): 
            a += self.xGrid [i] * map [i] 
            b += self.yGrid [i] * map [i]
        n = 255 - int ((math.sqrt (a**2 + b**2) * gain))
        if n < 0: n = -n
        if n > 255: n = 255
        return n
Times for SobelEdge, SobelEdge2, and SobelEdge3
    ncalls  tottime  percall  cumtime  percall filename:lineno(function)

        1    1.307    1.307    7.334    7.334 Filter.py:369(SobelEdge)
    15876    1.390    0.000    1.966    0.000 Filter.py:38(gradient)
    15876    0.988    0.000    2.694    0.000 PIL\Image.py:670(crop)
    15880    0.616    0.000    0.773    0.000 PIL\ImageFile.py:115(load)
    15876    0.602    0.000    0.934    0.000 PIL\Image.py:1546(__init__)
    15876    0.509    0.000    0.990    0.000 PIL\Image.py:1563(load)
    15876    0.481    0.000    0.481    0.000 :0(crop)
    15876    0.374    0.000    1.364    0.000 PIL\Image.py:793(getdata)
    15879    0.355    0.000    0.355    0.000 :0(range)
    15895    0.333    0.000    0.333    0.000 PIL\Image.py:392(__init__)
    15876    0.220    0.000    0.220    0.000 :0(sqrt)


        1    1.572    1.572    8.833    8.833 Filter.py:351(SobelEdge2)
    15876    1.343    0.000    1.964    0.000 Filter.py:38(gradient)
    15876    1.015    0.000    2.789    0.000 PIL\Image.py:670(crop)
    15880    0.656    0.000    0.805    0.000 PIL\ImageFile.py:115(load)
    16384    0.648    0.000    1.069    0.000 PIL\Image.py:1161(putpixel)
    15876    0.639    0.000    0.969    0.000 PIL\Image.py:1546(__init__)
    15876    0.504    0.000    0.504    0.000 :0(crop)
    15876    0.504    0.000    1.007    0.000 PIL\Image.py:1563(load)
    15876    0.430    0.000    1.438    0.000 PIL\Image.py:793(getdata)
    32275    0.335    0.000    0.335    0.000 PIL\Image.py:525(load)
    15894    0.331    0.000    0.331    0.000 PIL\Image.py:392(__init__)
    15879    0.318    0.000    0.318    0.000 :0(range)
    15876    0.303    0.000    0.303    0.000 :0(sqrt)
    16384    0.236    0.000    0.236    0.000 :0(putpixel)

        1    1.691    1.691   11.567   11.567 Filter.py:332(SobelEdge3)
    15876    1.562    0.000    2.268    0.000 Filter.py:38(gradient)
    15876    1.035    0.000    2.978    0.000 Image.py:670(crop)
    16384    0.775    0.000    2.009    0.000 ImageDraw.py:133(_getink)
    16384    0.747    0.000    3.138    0.000 ImageDraw.py:226(point)
    15880    0.732    0.000    0.943    0.000 ImageFile.py:115(load)
    15876    0.701    0.000    1.001    0.000 Image.py:1546(__init__)
    15876    0.546    0.000    0.546    0.000 :0(crop)
    16390    0.524    0.000    0.923    0.000 Image.py:79(isStringType)
    15876    0.488    0.000    1.490    0.000 Image.py:793(getdata)
    15876    0.456    0.000    1.002    0.000 Image.py:1563(load)
    15879    0.407    0.000    0.407    0.000 :0(range)
    32788    0.399    0.000    0.399    0.000 :0(isinstance)
    16384    0.381    0.000    0.381    0.000 :0(draw_points)
    16385    0.312    0.000    0.312    0.000 :0(draw_ink)
    15894    0.301    0.000    0.301    0.000 Image.py:392(__init__)
    15876    0.300    0.000    0.300    0.000 :0(sqrt)
    15892    0.211    0.000    0.211    0.000 Image.py:525(load)
__________________
Abstraction doesn't make it impossible to write bad code; it makes it possible to write superior code.
Contributor's Corner: Grumpy on C++ Exceptions DaWei on Pointers
DaWei is offline   Reply With Quote
Old Jul 12th, 2006, 1:58 PM   #27
DaWei
Resident Grouch
 
DaWei's Avatar
 
Join Date: Jun 2005
Posts: 6,453
Rep Power: 10 DaWei is on a distinguished road
Heh. My own BitList class.
        1    1.021    1.021    3.630    3.630 Filter.py:348(SobelEdge4)
    15876    1.310    0.000    1.935    0.000 Filter.py:54(gradient)
    15876    0.671    0.000    0.671    0.000 Filter.py:38(getMap)
    15879    0.360    0.000    0.360    0.000 :0(range)
    15876    0.265    0.000    0.265    0.000 :0(sqrt)
__________________
Abstraction doesn't make it impossible to write bad code; it makes it possible to write superior code.
Contributor's Corner: Grumpy on C++ Exceptions DaWei on Pointers
DaWei is offline   Reply With Quote
Reply

Bookmarks

« Previous Thread in Forum | Next Thread in Forum »

Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump




DaniWeb IT Discussion Community
All times are GMT -5. The time now is 10:28 AM.

Powered by vBulletin® Version 3.7.0, Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Copyright ©2007 DaniWeb® LLC