473,383 Members | 1,759 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,383 software developers and data experts.

Fastest Way To Loop Through Every Pixel

As my first attempt to loop through every pixel of an image, I used

for thisY in range(0, thisHeight):
for thisX in range(0, thisWidth):
#Actions here for Pixel thisX, thisY

But it takes 450-1000 milliseconds

I want speeds less than 10 milliseconds

I have tried using SWIG, and pypy but they all are unsuccessfull in
compiling my files.

Jul 28 '06 #1
30 9004

Chaos wrote:
As my first attempt to loop through every pixel of an image, I used

for thisY in range(0, thisHeight):
for thisX in range(0, thisWidth):
#Actions here for Pixel thisX, thisY
OT: you don't need the 0 in the range call. Taking it out doesn't make
it run faster, though.
>
But it takes 450-1000 milliseconds

I want speeds less than 10 milliseconds

I have tried using SWIG, and pypy but they all are unsuccessfull in
compiling my files.
Unsuccessful because .... what?
[I wasn't aware that swig was intended to compile Python scripts]

Sticking with Python:
With the "for thisX" try
(1) using xrange instead of range.
(2) widthRange = range(thisWidth)
for thisY in range(thisHeight):
for thisX in widthrange:
and in general, hoist loop-invariants outside the loop.

Have you considered Pyrex?

It all depends on what "#Actions here for Pixel thisX, thisY" is doing.
Perhaps there is a library (PIL, pygame, ...) that does what you are
trying to do.
Perhaps if you show us what you are doing, we can give you better
advice.

HTH,
John

Jul 28 '06 #2

John Machin wrote:
Chaos wrote:
As my first attempt to loop through every pixel of an image, I used

for thisY in range(0, thisHeight):
for thisX in range(0, thisWidth):
#Actions here for Pixel thisX, thisY

OT: you don't need the 0 in the range call. Taking it out doesn't make
it run faster, though.

But it takes 450-1000 milliseconds

I want speeds less than 10 milliseconds

I have tried using SWIG, and pypy but they all are unsuccessfull in
compiling my files.

Unsuccessful because .... what?
[I wasn't aware that swig was intended to compile Python scripts]

Sticking with Python:
With the "for thisX" try
(1) using xrange instead of range.
(2) widthRange = range(thisWidth)
for thisY in range(thisHeight):
for thisX in widthrange:
and in general, hoist loop-invariants outside the loop.

Have you considered Pyrex?

It all depends on what "#Actions here for Pixel thisX, thisY" is doing.
Perhaps there is a library (PIL, pygame, ...) that does what you are
trying to do.
Perhaps if you show us what you are doing, we can give you better
advice.

HTH,
John
Nope still same speed. I also tried pyrex but I couldnt understand how
to build pyx files. I didnt see how to set up the files using C. I
wasnt sure if you were supposed use the example or build your own.

With pypy I got a strange error trying to open py files. It said the
first character of evey py file was unknown.

I may try SWIG again becuase I fail to rememeber why I stopped using it.

Jul 28 '06 #3
Hello Chaos,

Whatever you do in "#Actions here ..." might be expressed nicely as a
ufunction for numeric. Then you might be able to convert the expression
to a numeric expression. Check out numpy/scipy.

In general, if thisHeight, thisWidth are large use xrange not range.
range() generates a list of numbers first then iterates through them.
So try that first.

Then of course if you do the whole thing many times you could just
pre-generate the indices as in:
all_indices=[]
for i in xrange(thisHeight):
for j in xrange(thisWidth):
all_indices.append( (i,j) )

Then each time you need to run '#Actions here...' you can just use
for (i,j) in all_indices:
#Actions here ... blah blah

In general, if there would be a way to significantly optimize generic
for loops, they would probably be already optimized...

Nick V.
Chaos wrote:
As my first attempt to loop through every pixel of an image, I used

for thisY in range(0, thisHeight):
for thisX in range(0, thisWidth):
#Actions here for Pixel thisX, thisY

But it takes 450-1000 milliseconds

I want speeds less than 10 milliseconds

I have tried using SWIG, and pypy but they all are unsuccessfull in
compiling my files.
Jul 28 '06 #4

Chaos wrote:
John Machin wrote:
Chaos wrote:
As my first attempt to loop through every pixel of an image, I used
>
for thisY in range(0, thisHeight):
for thisX in range(0, thisWidth):
#Actions here for Pixel thisX, thisY
OT: you don't need the 0 in the range call. Taking it out doesn't make
it run faster, though.
>
But it takes 450-1000 milliseconds
>
I want speeds less than 10 milliseconds
>
I have tried using SWIG, and pypy but they all are
unsuccessfull in
compiling my files.
Unsuccessful because .... what?
[I wasn't aware that swig was intended to compile Python scripts]

Sticking with Python:
With the "for thisX" try
(1) using xrange instead of range.
(2) widthRange = range(thisWidth)
for thisY in range(thisHeight):
for thisX in widthrange:
and in general, hoist loop-invariants outside the loop.

Have you considered Pyrex?

It all depends on what "#Actions here for Pixel thisX, thisY" is doing.
Perhaps there is a library (PIL, pygame, ...) that does what you are
trying to do.
Perhaps if you show us what you are doing, we can give you better
advice.

HTH,
John

Nope still same speed. I also tried pyrex but I couldnt understand how
to build pyx files. I didnt see how to set up the files using C. I
wasnt sure if you were supposed use the example or build your own.

With pypy I got a strange error trying to open py files. It said the
first character of evey py file was unknown.

I may try SWIG again becuase I fail to rememeber why I stopped using it.
With SWIG when I tried to execute ld -shared example.o example_wrap.o
-o _example.so line in CMD I got example_wrap.o:example.o
:<.text+0x####>: undifned refrence to object

--Nick

Thank you but it didnt work, but I think I am getting somewhere because
I used your method and got 400 ms, I think that is something because I
used 2 loops

He is the code #Actions here

myCol = (0.3 * image.GetRed(thisX, thisY)) + (0.59 *
image.GetGreen(thisX, thisY)) + (0.11 * image.GetBlue(thisX, thisY))
if myCol < darkestCol:
darkestCol = myCol
possX = thisX
possY = thisY

Jul 28 '06 #5
Chaos wrote:
As my first attempt to loop through every pixel of an image, I used

for thisY in range(0, thisHeight):
for thisX in range(0, thisWidth):
#Actions here for Pixel thisX, thisY

But it takes 450-1000 milliseconds

I want speeds less than 10 milliseconds

I have tried using SWIG, and pypy but they all are unsuccessfull in
compiling my files.
You could try the PIL package.
>From the docs at
http://www.pythonware.com/library/pi...book/image.htm

Image.eval(function, image) =image

Applies the function (which should take one argument) to each pixel in
the given image. If the image has more than one band, the same function
is applied to each band. Note that the function is evaluated once for
each possible pixel value, so you cannot use random components or other
generators.

HTH,
~Simon

Jul 28 '06 #6
Have you tried PIL? (Python Imaging Library)

"Chaos" <ps*******@gmail.comwrote:
>As my first attempt to loop through every pixel of an image, I used

for thisY in range(0, thisHeight):
for thisX in range(0, thisWidth):
#Actions here for Pixel thisX, thisY

But it takes 450-1000 milliseconds

I want speeds less than 10 milliseconds

I have tried using SWIG, and pypy but they all are unsuccessfull in
compiling my files.
--
Regards,
Casey
Jul 28 '06 #7

Simon Forman wrote:
Chaos wrote:
As my first attempt to loop through every pixel of an image, I used

for thisY in range(0, thisHeight):
for thisX in range(0, thisWidth):
#Actions here for Pixel thisX, thisY

But it takes 450-1000 milliseconds

I want speeds less than 10 milliseconds

I have tried using SWIG, and pypy but they all are unsuccessfull in
compiling my files.

You could try the PIL package.
From the docs at
http://www.pythonware.com/library/pi...book/image.htm

Image.eval(function, image) =image

Applies the function (which should take one argument) to each pixel in
the given image. If the image has more than one band, the same function
is applied to each band. Note that the function is evaluated once for
each possible pixel value, so you cannot use random components or other
generators.

HTH,
~Simon
I have tried PIL. Not only that, but the Image.eval function had no
success either. I did some tests and I found out that Image.eval only
called the function a certain number of times either 250, or 255.
Unless I can find a working example for this function, its impossible
to use.

Jul 28 '06 #8
"Chaos" <ps*******@gmail.comwrote in message
news:11**********************@i3g2000cwc.googlegro ups.com...
>

myCol = (0.3 * image.GetRed(thisX, thisY)) + (0.59 *
image.GetGreen(thisX, thisY)) + (0.11 * image.GetBlue(thisX, thisY))
if myCol < darkestCol:
darkestCol = myCol
possX = thisX
possY = thisY
Psyco may be of some help to you, especially if you extract out your myCol
expression into its own function, something like:

def darkness(img,x,y):
return (0.3 * img.GetRed(x,y)) + (0.59 * img.GetGreen(x,y)) + (0.11 *
img.GetBlue(x,y))

You may also be paying a penalty for the floating-point multiplications.
Since you are only concerned with the relative values, what if you scale up
all of your weighting coefficients, so that you only do integer multiplies?

def darkness(img,x,y):
return (30 * img.GetRed(x,y)) + (59 * img.GetGreen(x,y)) + (11 *
img.GetBlue(x,y))

You can also cut down on resolution of your GetXXX functions by saving them
to locals.

RedVal = Image.GetRed
GrnVal = Image.GetGreen
BluVal = Image.GetBlue
def darkness(img,x,y):
return (30 * RedVal(img,x,y)) + (59 * GreenVal(img,x,y)) + (11 *
BlueVal(img,x,y))

Even downer-and-dirtier, you could approximate 30 with 32, 59 with 64, and
11 with 8, and do bit-shifting instead of multiplying:

def darkness(img,x,y):
return (RedVal(img,x,y) << 5) + (GreenVal(img,x,y) << 6) +
(BlueVal(img,x,y) << 3)
-- Paul
Jul 28 '06 #9

"Nick Vatamaniuc" <va******@gmail.comwrote in message
news:11**********************@p79g2000cwp.googlegr oups.com...
Hello Chaos,

Then of course if you do the whole thing many times you could just
pre-generate the indices as in:
all_indices=[]
for i in xrange(thisHeight):
for j in xrange(thisWidth):
all_indices.append( (i,j) )
Or just:

all_indices = [ (i,j) for i in xrange(thisHeight) for j in
xrange(thisWidth) ]

Embrace those list comprehensions!

-- Paul
Jul 28 '06 #10
Chaos wrote:
Simon Forman wrote:
Chaos wrote:
As my first attempt to loop through every pixel of an image, I used
>
for thisY in range(0, thisHeight):
for thisX in range(0, thisWidth):
#Actions here for Pixel thisX, thisY
>
But it takes 450-1000 milliseconds
>
I want speeds less than 10 milliseconds
>
I have tried using SWIG, and pypy but they all are unsuccessfull in
compiling my files.
You could try the PIL package.
>From the docs at
http://www.pythonware.com/library/pi...book/image.htm

Image.eval(function, image) =image

Applies the function (which should take one argument) to each pixel in
the given image. If the image has more than one band, the same function
is applied to each band. Note that the function is evaluated once for
each possible pixel value, so you cannot use random components or other
generators.

HTH,
~Simon

I have tried PIL. Not only that, but the Image.eval function had no
success either. I did some tests and I found out that Image.eval only
called the function a certain number of times either 250, or 255.
It says "the function is evaluated once for each possible pixel value",
so if it's only calling the function 250 or 255 times it's because your
image only has 250 or 255 colors.

Obviously Image.eval() caches the results of your function for each
color/pixel-value and reuses them rather than recomputing them.

I take it that whatever you're doing to those pixels involves more
information than just the pixel values? What are you doing to the
pixels? That's probably wher you should look to improve the speed of
the loop.

Peace,
~Simon

Jul 28 '06 #11
"Paul McGuire" <pt***@austin.rr._bogus_.comwrote:

| Even downer-and-dirtier, you could approximate 30 with 32, 59 with 64, and
| 11 with 8, and do bit-shifting instead of multiplying:
|
| def darkness(img,x,y):
| return (RedVal(img,x,y) << 5) + (GreenVal(img,x,y) << 6) +
| (BlueVal(img,x,y) << 3)
|
|
| -- Paul

*grin* - a man after my own heart! - how do you multiply by ten? - shift, save a
copy, shift twice more and add the copy...

- Hendrik

Jul 28 '06 #12
Simon Forman wrote:
Chaos wrote:
Simon Forman wrote:
Chaos wrote:
As my first attempt to loop through every pixel of an image, I used

for thisY in range(0, thisHeight):
for thisX in range(0, thisWidth):
#Actions here for Pixel thisX, thisY

But it takes 450-1000 milliseconds

I want speeds less than 10 milliseconds

I have tried using SWIG, and pypy but they all are unsuccessfull in
compiling my files.
>
You could try the PIL package.
>
From the docs at
http://www.pythonware.com/library/pi...book/image.htm
>
Image.eval(function, image) =image
>
Applies the function (which should take one argument) to each pixel in
the given image. If the image has more than one band, the same function
is applied to each band. Note that the function is evaluated once for
each possible pixel value, so you cannot use random components or other
generators.
>
HTH,
~Simon
I have tried PIL. Not only that, but the Image.eval function had no
success either. I did some tests and I found out that Image.eval only
called the function a certain number of times either 250, or 255.

It says "the function is evaluated once for each possible pixel value",
so if it's only calling the function 250 or 255 times it's because your
image only has 250 or 255 colors.

Obviously Image.eval() caches the results of your function for each
color/pixel-value and reuses them rather than recomputing them.

I take it that whatever you're doing to those pixels involves more
information than just the pixel values? What are you doing to the
pixels? That's probably wher you should look to improve the speed of
the loop.

Peace,
~Simon
Oops, sorry. I didn't see where you had already posted the actions
you're taking on the pixels..

He is the code #Actions here

myCol = (0.3 * image.GetRed(thisX, thisY)) + (0.59 *
image.GetGreen(thisX, thisY)) + (0.11 * image.GetBlue(thisX, thisY))
if myCol < darkestCol:
darkestCol = myCol
possX = thisX
possY = thisY

Hmm, if you're just trying to find the darkest color and one of it's
pixel coordinates after applying your weighting calculation, and you
don't mind if the coordinates are of the first encountered pixel of
that color, then I think you might be able to use Image.eval() after
all.

What format are the images in?
Peace,
~Simon

Jul 28 '06 #13
"H J van Rooyen" <ma**@microcorp.co.zawrote in message
news:ma***************************************@pyt hon.org...
"Paul McGuire" <pt***@austin.rr._bogus_.comwrote:

| Even downer-and-dirtier, you could approximate 30 with 32, 59 with 64,
and
| 11 with 8, and do bit-shifting instead of multiplying:
|
| def darkness(img,x,y):
| return (RedVal(img,x,y) << 5) + (GreenVal(img,x,y) << 6) +
| (BlueVal(img,x,y) << 3)
|
|
| -- Paul

*grin* - a man after my own heart! - how do you multiply by ten? - shift,
save a
copy, shift twice more and add the copy...

- Hendrik
Sadly, my timeit results show this saves only a little time, and
shift-copy-shiftsomemore-and-add is even slower then just doing the original
floating point multiply. The biggest win is in prelookup of Image.GetXXX
functions.

-- Paul
Jul 28 '06 #14
Chaos wrote:
As my first attempt to loop through every pixel of an image, I used

for thisY in range(0, thisHeight):
for thisX in range(0, thisWidth):
#Actions here for Pixel thisX, thisY

But it takes 450-1000 milliseconds

I want speeds less than 10 milliseconds
The main question is: why do you want to do this? I ask because with
performance requirements like that, you almost certainly need another
approach, one which I may be able to suggest.

--
Ben Sizer

Jul 28 '06 #15
Chaos (ps*******@gmail.com) wrote:

: He is the code #Actions here

: myCol = (0.3 * image.GetRed(thisX, thisY)) + (0.59 *
: image.GetGreen(thisX, thisY)) + (0.11 * image.GetBlue(thisX, thisY))
: if myCol < darkestCol:
: darkestCol = myCol
: possX = thisX
: possY = thisY

You really don't want to do this in interpreted Python code. Way to slow.
I don't know PIL but probably you can do it their.

Another aproach is to use one of the array/maths libraries e.g. Numeric or
NumPy.

You'll need to move the image data between PIL and the array package with
the data being a (y,x,3) array for input array and (y,x) for the output
array. .tostirng() methods and fromstring() can be usefull here.

Then...

1. Colour map it
newImage = 0.3 * image[:,:,0] + 0.59 * image[:,:,1] + 0.11 * image[:,:,2]

2. Mask of pixels less than your threshold

newImage = clip(newImage, myCol, MAX_COLOUR)

3. Find the coordinates of the last minimum colour - possX, possY (do you
really need/mean to do this?)

hth
cds
Jul 28 '06 #16

"Paul McGuire" <pt***@austin.rr._bogus_.comwrote:

| "H J van Rooyen" <ma**@microcorp.co.zawrote in message
| news:ma***************************************@pyt hon.org...
| "Paul McGuire" <pt***@austin.rr._bogus_.comwrote:
| >
| | Even downer-and-dirtier, you could approximate 30 with 32, 59 with 64,
| and
| | 11 with 8, and do bit-shifting instead of multiplying:
| |
| | def darkness(img,x,y):
| | return (RedVal(img,x,y) << 5) + (GreenVal(img,x,y) << 6) +
| | (BlueVal(img,x,y) << 3)
| |
| |
| | -- Paul
| >
| *grin* - a man after my own heart! - how do you multiply by ten? - shift,
| save a
| copy, shift twice more and add the copy...
| >
| - Hendrik
| >
| Sadly, my timeit results show this saves only a little time, and
| shift-copy-shiftsomemore-and-add is even slower then just doing the original
| floating point multiply. The biggest win is in prelookup of Image.GetXXX
| functions.
|
| -- Paul

I was not seriously suggesting this for use in python on a pc - its the sort of
rubbish you do on a small embedded machine that has a reduced instruction set
and no multiplier...

- Hendrik

Jul 28 '06 #17
Chaos wrote:
As my first attempt to loop through every pixel of an image, I used

for thisY in range(0, thisHeight):
for thisX in range(0, thisWidth):
#Actions here for Pixel thisX, thisY

But it takes 450-1000 milliseconds

I want speeds less than 10 milliseconds

I have tried using SWIG, and pypy but they all are unsuccessfull in
compiling my files.
I think you are using PIL but I don't know what version.

Check out this page.
http://effbot.org/zone/image-histogram-optimization.htm

HTH...
jay

Jul 28 '06 #18

"Chaos" <ps*******@gmail.comwrote in message
news:11*********************@i3g2000cwc.googlegrou ps.com...
As my first attempt to loop through every pixel of an image, I used

for thisY in range(0, thisHeight):
for thisX in range(0, thisWidth):
#Actions here for Pixel thisX, thisY
Besides other suggestions, you might also take a look at Pygame which both
wraps a C graphics library and has an interface to numeric.


Jul 28 '06 #19

Terry Reedy wrote:
"Chaos" <ps*******@gmail.comwrote in message
news:11*********************@i3g2000cwc.googlegrou ps.com...
As my first attempt to loop through every pixel of an image, I used

for thisY in range(0, thisHeight):
for thisX in range(0, thisWidth):
#Actions here for Pixel thisX, thisY

Besides other suggestions, you might also take a look at Pygame which both
wraps a C graphics library and has an interface to numeric.
:-)
Could your check_earlier_responses() gizmoid be made case-insensitive?
(-:

Jul 28 '06 #20
Chaos wrote:
As my first attempt to loop through every pixel of an image, I used

for thisY in range(0, thisHeight):
for thisX in range(0, thisWidth):
#Actions here for Pixel thisX, thisY

But it takes 450-1000 milliseconds

I want speeds less than 10 milliseconds
Milliseconds don't mean much unless we knew how big your images are and
what hardware you're using.

Have you considered using NumPy? Assuming you can get the image into a
numpy array efficiently, the actual algorithm boils down to something
like this:

grey = r*0.3 + g*0.59 + b*0.11
index = grey.argmin()
x,y = index%step, index/step
v = grey[x,y]

where r,g,b and grey are numpy.ndarray objects; The arithmetic
operators and the argmin-function are implemented in C, so you can
expect decent performance. (the 4 lines above take about 80 ms for a
1000x1000 image on my PC)

If that's not enough, you might want to use some specially optimized C
library for this purpose. (I'd suggest Intel's IPP, but there are
others).

Jul 28 '06 #21

nikie wrote:
Chaos wrote:
As my first attempt to loop through every pixel of an image, I used

for thisY in range(0, thisHeight):
for thisX in range(0, thisWidth):
#Actions here for Pixel thisX, thisY

But it takes 450-1000 milliseconds

I want speeds less than 10 milliseconds

Milliseconds don't mean much unless we knew how big your images are and
what hardware you're using.

Have you considered using NumPy? Assuming you can get the image into a
numpy array efficiently, the actual algorithm boils down to something
like this:

grey = r*0.3 + g*0.59 + b*0.11
index = grey.argmin()
x,y = index%step, index/step
v = grey[x,y]

where r,g,b and grey are numpy.ndarray objects; The arithmetic
operators and the argmin-function are implemented in C, so you can
expect decent performance. (the 4 lines above take about 80 ms for a
1000x1000 image on my PC)

If that's not enough, you might want to use some specially optimized C
library for this purpose. (I'd suggest Intel's IPP, but there are
others).
Can you give me an example of geting an image into a numpy array?

Jul 29 '06 #22

nikie wrote:
Chaos wrote:
As my first attempt to loop through every pixel of an image, I used

for thisY in range(0, thisHeight):
for thisX in range(0, thisWidth):
#Actions here for Pixel thisX, thisY

But it takes 450-1000 milliseconds

I want speeds less than 10 milliseconds

Milliseconds don't mean much unless we knew how big your images are and
what hardware you're using.

Have you considered using NumPy? Assuming you can get the image into a
numpy array efficiently, the actual algorithm boils down to something
like this:

grey = r*0.3 +
g*0.59 + b*0.11
index = grey.argmin()
x,y = index%step, index/step
v = grey[x,y]

where r,g,b and grey are numpy.ndarray objects; The arithmetic
operators and the argmin-function are implemented in C, so you can
expect decent performance. (the 4 lines above take about 80 ms for a
1000x1000 image on my PC)

If that's not enough, you might want to use some specially optimized C
library for this purpose. (I'd suggest Intel's IPP, but there are
others).
I really do not understand the code. Where did you get the varibales r,
g, b and step and what does v produce?

Jul 29 '06 #23
Chaos wrote:
As my first attempt to loop through every pixel of an image, I used

for thisY in range(0, thisHeight):
for thisX in range(0, thisWidth):
#Actions here for Pixel thisX, thisY

But it takes 450-1000 milliseconds

I want speeds less than 10 milliseconds

I have tried using SWIG, and pypy but they all are unsuccessfull in
compiling my files.
This probably won't work for you, but it's worth suggesting as it may
give you other ideas to solve your problem.

If it is a list of lists of pixel objects you can iterate though the
pixels directly and not use range or xrange at all. For this to work
the pixel object needs to be mutable or have an attribute to store it's
value. It can't be just an int, in that case you will need to use indexes.

pixel = [rgb_value]

or

pixel = [r,g,b]

or

class Pixel(object):
def __self__(self, rgb_value):
self.value = rgb_value
pixel = Pixel(rgb_value)

Or some other variation that is mutable.
These may not be suitable and may cause additional overhead elsewhere as
the image may need to be converted to some other form in order to
display or save it.

What Actions are you performing on the pixels?

You may be able to increase the speed by creating lookup tables in
dictionaries and then use the pixel value for the key.
Just a rough example...

action1 = dict()
# fill dict with precomputed pixel key value pairs.
# ...

image = getimage()
for row in image:
for pixel in row:
# one of the following or something similar
pixel[0] = action1[pixel]
pixel.value = action1[pixel.value]
pixel[:] = action[pixel]
The pixels need to be objects so they are mutable. If they aren't, then
you will need to use index's as you did above.

Precomputing the pixel value tables may use up too much memory or take a
very long time if your image has a large amount of possible colors. If
precomputing the pixels take too long but you are not concerned by the
memory usage, you may be able to store (pickle) the precomputed tables
then unpickle it before it is used.

This work best if the number of colors (the depth) is limited.

If these suggestions aren't applicable, then you most likely need to
look at an image library that uses compiled C (or assembly) code to do
the brute force work. It may also be possible to access your platforms
directX or opengl library routines directly to do it.

Cheers,
Ron




Jul 29 '06 #24
"Paul McGuire" <pt***@austin.rr._bogus_.comwrote in message
news:Gr*******************@tornado.texas.rr.com...
"Chaos" <ps*******@gmail.comwrote in message
news:11**********************@i3g2000cwc.googlegro ups.com...


myCol = (0.3 * image.GetRed(thisX, thisY)) + (0.59 *
image.GetGreen(thisX, thisY)) + (0.11 * image.GetBlue(thisX, thisY))
if myCol < darkestCol:
darkestCol = myCol
possX = thisX
possY = thisY

Psyco may be of some help to you, especially if you extract out your myCol
expression into its own function, something like:

def darkness(img,x,y):
return (0.3 * img.GetRed(x,y)) + (0.59 * img.GetGreen(x,y)) + (0.11 *
img.GetBlue(x,y))
<snip>

Even better than my other suggestions might be to write this function, and
then wrap it in a memoizing decorator
(http://wiki.python.org/moin/PythonDe...a08b0fa59a8622
201abfac735ea47ffade5) - surely there must be some repeated colors in your
image.

-- Paul

Jul 29 '06 #25

Paul McGuire wrote:
"Paul McGuire" <pt***@austin.rr._bogus_.comwrote in message
news:Gr*******************@tornado.texas.rr.com...
"Chaos" <ps*******@gmail.comwrote in message
news:11**********************@i3g2000cwc.googlegro ups.com...
>
>
myCol = (0.3 * image.GetRed(thisX, thisY)) + (0.59 *
image.GetGreen(thisX, thisY)) + (0.11 * image.GetBlue(thisX, thisY))
if myCol < darkestCol:
darkestCol = myCol
possX = thisX
possY = thisY
>
Psyco may be of some help to you, especially if you extract out your myCol
expression into its own function, something like:

def darkness(img,x,y):
return (0.3 * img.GetRed(x,y)) + (0.59 * img.GetGreen(x,y)) + (0.11 *
img.GetBlue(x,y))
<snip>

Even better than my other suggestions might be to write this function, and
then wrap it in a memoizing decorator
(http://wiki.python.org/moin/PythonDe...a08b0fa59a8622
201abfac735ea47ffade5) - surely there must be some repeated colors in your
image.

-- Paul
Its not only finding the darkest color, but also finding the X position
and Y Position of the darkest color.

Jul 30 '06 #26
Chaos wrote:
nikie wrote:
Chaos wrote:
As my first attempt to loop through every pixel of an image, I used
>
for thisY in range(0, thisHeight):
for thisX in range(0, thisWidth):
#Actions here for Pixel thisX, thisY
>
But it takes 450-1000 milliseconds
>
I want speeds less than 10 milliseconds
Milliseconds don't mean much unless we knew how big your images are and
what hardware you're using.

Have you considered using NumPy? Assuming you can get the image into a
numpy array efficiently, the actual algorithm boils down to something
like this:

grey = r*0.3 +

g*0.59 + b*0.11
index = grey.argmin()
x,y = index%step, index/step
v = grey[x,y]

where r,g,b and grey are numpy.ndarray objects; The arithmetic
operators and the argmin-function are implemented in C, so you can
expect decent performance. (the 4 lines above take about 80 ms for a
1000x1000 image on my PC)

If that's not enough, you might want to use some specially optimized C
library for this purpose. (I'd suggest Intel's IPP, but there are
others).

I really do not understand the code. Where did you get the varibales r,
g, b and step and what does v produce?
Sorry, I should have commented it better. The idea is that r,g,b are
numpy-arrays containig the r, g, b-pixel-values in the image:

import numpy, Image
img = Image.open("Image1.jpg")
r = numpy.array(img.getdata(0))
g = numpy.array(img.getdata(1))
b = numpy.array(img.getdata(2))
w,h = img.size

The "step" is the length of one line of pixels, that is, the offset to
a pixel (x,y) is x+y*step. (This is usually called "step" or "stride"
in literature)

step = w

Now, I can use numpy's overridden arithmetic operators to do the
per-pixel calculations (Note that numpy also overrides sin, cos, max,
...., but you'll have to use from numpy import * to get these overrides
in your namespace):

grey = r*0.3 + g*0.59 + b*0.11

The multiplication-operator is overridden, so that "r*0.3" multiplies
each value in the array "r" with "0.3" and returns the multiplied
array, same for "g*0.59", "b*0.11". Adding the arrays adds them up
value by value, and returns the sum array. This generally works quite
well and intuitively if you perform only per-pixel operations. If you
need a neighborhood, use slicing.
The function "argmin" searches for the index of the minimum value in
the array:

index = grey.argmin()

But since we want coordinates instead of indices, we'll have to
transform these back using the step value:

x,y = index % step, index / step

Result:

print x,y,r[index],g[index],b[index]

Works for my image.

Notes:
- I'm _not_ sure if this is the fastest way to get an image into a
numpy array. It's convenient, but if you need speed, digging into the
numpy docs/newsgroup archive, and doing a few benchmarks for yourself
would be a good idea
- numpy does have 2d-Arrays, but I'm not that much of a numpy expert to
tell you how to use that to get rid of the index/step-calculations.
Again, numpy-docs/newsgroup might help
- a general advice: using integer multiplications instead for
floating-point may help with performance, too.
- you said something about 10 ms, so I'm guessing your image doesn't
come from a harddrive at all (because reading it alone will usually
take longer than 10 ms). Numpy arrays have a C-Interface you might want
to use to get data from a framegrabber/digital camera into a numpy
array.

Jul 31 '06 #27
"Chaos" <ps*******@gmail.comwrote in message
news:11**********************@i42g2000cwa.googlegr oups.com...
>
Paul McGuire wrote:
"Paul McGuire" <pt***@austin.rr._bogus_.comwrote in message
news:Gr*******************@tornado.texas.rr.com...
"Chaos" <ps*******@gmail.comwrote in message
news:11**********************@i3g2000cwc.googlegro ups.com...


myCol = (0.3 * image.GetRed(thisX, thisY)) + (0.59 *
image.GetGreen(thisX, thisY)) + (0.11 * image.GetBlue(thisX, thisY))
if myCol < darkestCol:
darkestCol = myCol
possX = thisX
possY = thisY

>
Psyco may be of some help to you, especially if you extract out your
myCol
expression into its own function, something like:
>
def darkness(img,x,y):
return (0.3 * img.GetRed(x,y)) + (0.59 * img.GetGreen(x,y)) +
(0.11 *
img.GetBlue(x,y))
>
<snip>

Even better than my other suggestions might be to write this function,
and
then wrap it in a memoizing decorator
(http://wiki.python.org/moin/PythonDe...a08b0fa59a8622
201abfac735ea47ffade5) - surely there must be some repeated colors in
your
image.

-- Paul

Its not only finding the darkest color, but also finding the X position
and Y Position of the darkest color.
Sorry, you are correct. To take advantage of memoizing, the darkness method
would have to work with the r, g, and b values, not the x's and y's.

-- Paul
import psyco
psyco.full()

IMAGE_WIDTH = 200
IMAGE_HEIGHT = 200
imgColRange = range(IMAGE_WIDTH)
imgRowRange = range(IMAGE_HEIGHT)

@memoize # copy memoize from
http://wiki.python.org/moin/PythonDecoratorLibrary, or similar
def darkness(r,g,b):
return 0.3*r + 0.59*g + 0.11*b

def getDarkestPixel(image):
getR = image.GetRed
getG = image.GetGreen
getB = image.GetBlue

darkest = darkness( getR(0,0), getG(0,0), getB(0,0) )
# or with PIL, could do
# darkest = darkness( *getpixel(0,0) )
dkX = 0
dkY = 0
for r in imgRowRange:
for c in imgColRange:
dk = darkness( getRed(r,c), getGrn(r,c), getBlu(r,c) )
if dk < darkest:
darkest = dk
dkX = c
dkY = r
return dkX, dkY

Jul 31 '06 #28
Paul McGuire wrote:
"Chaos" <ps*******@gmail.comwrote in message
news:11**********************@i42g2000cwa.googlegr oups.com...

Paul McGuire wrote:
"Paul McGuire" <pt***@austin.rr._bogus_.comwrote in message
news:Gr*******************@tornado.texas.rr.com...
"Chaos" <ps*******@gmail.comwrote in message
news:11**********************@i3g2000cwc.googlegro ups.com...
>
>
myCol = (0.3 * image.GetRed(thisX, thisY)) + (0.59 *
image.GetGreen(thisX, thisY)) + (0.11 * image.GetBlue(thisX, thisY))
if myCol < darkestCol:
darkestCol = myCol
possX = thisX
possY = thisY
>

Psyco may be of some help to you, especially if you extract out your
myCol
expression into its own function, something like:

def darkness(img,x,y):
return (0.3 * img.GetRed(x,y)) + (0.59 * img.GetGreen(x,y)) +
(0.11 *
img.GetBlue(x,y))

<snip>
>
Even better than my other suggestions might be to write this function,
and
then wrap it in a memoizing decorator
>
(http://wiki.python.org/moin/PythonDe...a08b0fa59a8622
201abfac735ea47ffade5) - surely there must be some repeated colors in
your
image.
>
-- Paul
Its not only finding the darkest color, but also finding the X position
and Y Position of the darkest color.

Sorry, you are correct. To take advantage of memoizing, the darkness method
would have to work with the r, g, and b values, not the x's and y's.

-- Paul
import psyco
psyco.full()

IMAGE_WIDTH = 200
IMAGE_HEIGHT = 200
imgColRange = range(IMAGE_WIDTH)
imgRowRange = range(IMAGE_HEIGHT)

@memoize # copy memoize from
http://wiki.python.org/moin/PythonDecoratorLibrary, or similar
def darkness(r,g,b):
return 0.3*r + 0.59*g + 0.11*b

def getDarkestPixel(image):
getR = image.GetRed
getG = image.GetGreen
getB = image.GetBlue

darkest = darkness( getR(0,0), getG(0,0), getB(0,0) )
# or with PIL, could do
# darkest = darkness( *getpixel(0,0) )
dkX = 0
dkY = 0
for r in imgRowRange:
for c in imgColRange:
dk = darkness( getRed(r,c), getGrn(r,c), getBlu(r,c) )
if dk < darkest:
darkest = dk
dkX = c
dkY = r
return dkX, dkY
>From my experiences with Psyco/PIL, it's probably faster to move the
image data into lists first (using list(Image.getdata) or
list(image.getband)) and access the raw data in your loop(s). Don't use
Image.getpixel in a tight loop, they result in Python-to-C-Calls which
can't be optimized by Psyco. Even when you're not using Psyco, getpixel
is probably slower (at least the PIL docs say so: "Note that this
method is rather slow; if you need to process larger parts of an image
from Python, use the getdata method.")

Jul 31 '06 #29
Chaos wrote:
I have tried PIL. Not only that, but the Image.eval function had no
success either. I did some tests and I found out that Image.eval only
called the function a certain number of times either 250, or 255.
Unless I can find a working example for this function, its impossible
to use.
you might have better success by asking questions about the problem
you're trying to solve, rather than about some artifact of your first
attempt to solve it...

the following PIL snippet locates the darkest pixel in an image in about
0.5 milliseconds for a 200x200 RGB image, on my machine:

im = im.convert("L") # convert to grayscale
lo, hi = im.getextrema() # find darkest pixel value
lo = im.point(lambda x: x == lo) # highlight darkest pixel value
x, y, _, _ = lo.getbbox() # locate uppermost/leftmost dark pixel

</F>

Jul 31 '06 #30

Fredrik Lundh wrote:
Chaos wrote:
I have tried PIL. Not only that, but the Image.eval function had no
success either. I did some tests and I found out that Image.eval only
called the function a certain number of times either 250, or 255.
Unless I can find a working example for this function, its impossible
to use.

you might have better success by asking questions about the problem
you're trying to solve, rather than about some artifact of your first
attempt to solve it...

the following PIL snippet locates the darkest pixel in an image in about
0.5 milliseconds for a 200x200 RGB image, on my machine:

im = im.convert("L") # convert to grayscale
lo, hi = im.getextrema() # find darkest pixel value
lo = im.point(lambda x: x == lo) # highlight darkest pixel value
x, y, _, _ = lo.getbbox() # locate uppermost/leftmost dark pixel

</F>
thank you that worked perfectly.

Aug 5 '06 #31

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

17
by: DraguVaso | last post by:
Hi, I need to find the FASTEST way to get a string in a Loop, that goes from "a" to "ZZZZZZZZZZZZZZZZZ". So it has to go like this: a b .... z
3
by: Lance | last post by:
What is the fastest way to determine if two arrays that contain ValueTypes are equal? For example, lets say I have the following: Dim pt1 as New Drawing.Point(1, 2) Dim pt2 as New...
44
by: Don Kim | last post by:
Ok, so I posted a rant earlier about the lack of marketing for C++/CLI, and it forked over into another rant about which was the faster compiler. Some said C# was just as fast as C++/CLI, whereas...
7
by: kebalex | last post by:
Hi, I have an app (written in .NET 2.0) which updates a picturebox according to some user input (a slider control). when the user makes a change i loop through all of the pixels, do a...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.