Fastest Way To Loop Through Every Pixel
27 answers - 376 bytes -

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.
No.1 | | 1165 bytes |
| 
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
T: 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
No.2 | | 1609 bytes |
| 
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
T: 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.
No.3 | | 1288 bytes |
| 
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.
No.4 | | 2238 bytes |
| 
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
T: 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
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
No.5 | | 861 bytes |
| 
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
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
No.6 | | 569 bytes |
| 
Have you tried PIL? (Python Imaging Library)
"Chaos" <psnim2000 (AT) gmail (DOT) 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.
No.7 | | 1189 bytes |
| 
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
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.
No.8 | | 1555 bytes |
| 
"Chaos" <psnim2000 (AT) gmail (DOT) comwrote in message
news:1154055002.495073.171650 (AT) i3g2000cwc (DOT) googlegroups.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
No.9 | | 494 bytes |
| 
"Nick Vatamaniuc" <vatamane (AT) gmail (DOT) comwrote in message
news:1154053874.100840.122250@
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) )
just:
all_indices = [ (i,j) for i in xrange(thisHeight) for j in
xrange(thisWidth) ]
Embrace those list comprehensions!
-- Paul
No.10 | | 1717 bytes |
| 
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
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.
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
No.11 | | 518 bytes |
| 
"Paul McGuire" <ptmcg (AT) austin (DOT) 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
No.12 | | 2482 bytes |
| 
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
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.
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
, 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
No.13 | | 836 bytes |
| 
"H J van Rooyen" <mail (AT) microcorp (DOT) co.zawrote in message
@python.org
"Paul McGuire" <ptmcg (AT) austin (DOT) 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
is even slower then just doing the original
floating point multiply. The biggest win is in prelookup of Image.GetXXX
functions.
-- Paul
No.14 | | 489 bytes |
| 
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.
No.15 | | 1123 bytes |
| 
Chaos (psnim2000 (AT) gmail (DOT) 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_CLUR)
3. Find the coordinates of the last minimum colour - possX, possY (do you
really need/mean to do this?)
hth
cds
No.16 | | 1181 bytes |
| 
"Paul McGuire" <ptmcg (AT) austin (DOT) rr._bogus_.comwrote:
| "H J van Rooyen" <mail (AT) microcorp (DOT) co.zawrote in message
| @python.org
| "Paul McGuire" <ptmcg (AT) austin (DOT) 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
| 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
No.17 | | 504 bytes |
| 
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.
HTH
jay
No.18 | | 541 bytes |
| 
"Chaos" <psnim2000 (AT) gmail (DOT) comwrote in message
news:1154053723.899787.72980 (AT) i3g2000cwc (DOT) googlegroups.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.
No.19 | | 659 bytes |
| 
Terry Reedy wrote:
"Chaos" <psnim2000 (AT) gmail (DOT) comwrote in message
news:1154053723.899787.72980 (AT) i3g2000cwc (DOT) googlegroups.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?
(-:
No.20 | | 1111 bytes |
| 
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).
No.21 | | 1196 bytes |
| 
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?
No.22 | | 1252 bytes |
| 
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?
No.23 | | 2621 bytes |
| 
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)
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
No.24 | | 1021 bytes |
| 
"Paul McGuire" <ptmcg (AT) austin (DOT) rr._bogus_.comwrote in message
news:Grhyg.21879$Cn6.17684 (AT) tornado (DOT) texas.rr.com
"Chaos" <psnim2000 (AT) gmail (DOT) comwrote in message
news:1154055002.495073.171650 (AT) i3g2000cwc (DOT) googlegroups.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
(#head-11870a08b0fa59a8622
201abfac735ea47ffade5) - surely there must be some repeated colors in your
image.
-- Paul
No.25 | | 1167 bytes |
| 
Paul McGuire wrote:
"Paul McGuire" <ptmcg (AT) austin (DOT) rr._bogus_.comwrote in message
news:Grhyg.21879$Cn6.17684 (AT) tornado (DOT) texas.rr.com
"Chaos" <psnim2000 (AT) gmail (DOT) comwrote in message
news:1154055002.495073.171650 (AT) i3g2000cwc (DOT) googlegroups.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
(#head-11870a08b0fa59a8622
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.
No.26 | | 3721 bytes |
| 
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.
No.27 | | 953 bytes |
| 
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.