473,713 Members | 5,030 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Newbie question about tuples and list comprehensions

Hi all - Sorry to plague you with another newbie question from a
lurker. Hopefully, this will be simple.

I have a list full of RGB pixel values read from an image. I want to
test each RGB band value per pixel, and set it to something else if it
meets or falls below a certain threshold - i.e., a Red value of 0
would be changed to 50.

I've built my list by using a Python Image Library statement akin to
the following:

data = list(image.getd ata())

Which produces a very long list that looks like [(0,150,175),
(50,175,225),.. .]. I'm trying to figure out a fast and pythonic way
to perform my operation. The closest I've come so far to a succinct
statement is a list comprehension along the syntax of:

source = [((x,y,z),(x+50, y+50,z+50))[bool(x or y or z < 50)] for
(x,y,z) in source]

....which kind of approaches the effect I'm looking for, but it doesn't
really test and change each value in the tuple individually. My
understanding of the things you can do with lists and python in
general is rather naive, so I would appreciate any insight anyone can
offer since I am not sure if I'm even headed down the correct path
with list comprehensions.

Much obliged!
Jun 27 '08 #1
7 1513
On Jun 25, 2:37*pm, idiolect <boingy.boi...@ gmail.comwrote:
Hi all - Sorry to plague you with another newbie question from a
lurker. *Hopefully, this will be simple.

I have a list full of RGB pixel values read from an image. *I want to
test each RGB band value per pixel, and set it to something else if it
meets or falls below a certain threshold - i.e., a Red value of 0
would be changed to 50.

I've built my list by using a Python Image Library statement akin to
the following:

data = list(image.getd ata())

Which produces a very long list that looks like [(0,150,175),
(50,175,225),.. .]. *I'm trying to figure out a fast and pythonic way
to perform my operation. *The closest I've come so far to a succinct
statement is a list comprehension along the syntax of:

source = [((x,y,z),(x+50, y+50,z+50))[bool(x or y or z < 50)] for
(x,y,z) in source]

...which kind of approaches the effect I'm looking for, but it doesn't
really test and change each value in the tuple individually. *My
understanding of the things you can do with lists and python in
general is rather naive, so I would appreciate any insight anyone can
offer since I am not sure if I'm even headed down the correct path
with list comprehensions.

Much obliged!
List comprehension is just a tool. If it looks more complicated than
it would if you used a regular for loop, then use a regular for loop.

It seems like you are evaluating a lot of data, so I would take
advantage of pythons (lazy) generators to save a lot of memory:

def brighten(seq, threshold=50): # I don't know what the generic name
for this operation is
for pixel in seq:
if any(channel < threshold for channel in pixel):
r, g, b = pixel
yield r + threshold, g + threshold, b + threshold

then...

source = brighten(image. getdata())

Source is going to be a lazy generator, so you can cast it to list, or
just pass it to something else that takes a sequence. The latter is
preferred.

Matt
Jun 27 '08 #2
On Jun 26, 7:37 am, idiolect <boingy.boi...@ gmail.comwrote:
Hi all - Sorry to plague you with another newbie question from a
lurker. Hopefully, this will be simple.

I have a list full of RGB pixel values read from an image. I want to
test each RGB band value per pixel, and set it to something else if it
meets or falls below a certain threshold - i.e., a Red value of 0
would be changed to 50.

I've built my list by using a Python Image Library statement akin to
the following:

data = list(image.getd ata())

Which produces a very long list that looks like [(0,150,175),
(50,175,225),.. .]. I'm trying to figure out a fast and pythonic way
to perform my operation. The closest I've come so far to a succinct
statement is a list comprehension along the syntax of:

source = [((x,y,z),(x+50, y+50,z+50))[bool(x or y or z < 50)] for
(x,y,z) in source]

...which kind of approaches the effect I'm looking for, but it doesn't
really test and change each value in the tuple individually. My
understanding of the things you can do with lists and python in
general is rather naive, so I would appreciate any insight anyone can
offer since I am not sure if I'm even headed down the correct path
with list comprehensions.
"x or y or z < 50" doesn't do what you think it does:
>>x, y, z = 120, 130, 140
x or y or z < 50
120
>>((x or y) or z) < 50
False
>>x or (y or (z < 50))
120
>>>
Here's one approach (requires Python 2.5 or later):
[(50 if x < 50 else x, 50 if y < 50 else y, 50 if z < 50 else z) for
(x, y, z) in source]
Jun 27 '08 #3
First, I second Matt's comment about using a boring old for loop when
it is the simplest way to express what you want to do. Being Pythonic
is not about using exotic features to scrunch your code down to a cool
one-liner. It is about expressing your intentions in a simple, direct
way. Sometimes comprehensions, generators, etc. help. Sometimes they
only obfuscate.

That said, the *most* Pythonic way to do something is to find the
existing library that already does it. Check out the Image.point()
function in the PIL documentation. You may not need to convert the
image to a list at all.

- Roger
Jun 27 '08 #4


idiolect wrote:
Hi all - Sorry to plague you with another newbie question from a
lurker. Hopefully, this will be simple.

I have a list full of RGB pixel values read from an image. I want to
test each RGB band value per pixel, and set it to something else if it
meets or falls below a certain threshold - i.e., a Red value of 0
would be changed to 50.

I've built my list by using a Python Image Library statement akin to
the following:

data = list(image.getd ata())

Which produces a very long list that looks like [(0,150,175),
(50,175,225),.. .]. I'm trying to figure out a fast and pythonic way
to perform my operation. The closest I've come so far to a succinct
statement is a list comprehension along the syntax of:
Why are you trying to do this with a list comprehension? Learn the
basics first. Perhaps you have read too many of the recent threads
presenting diverting challenges for bored experienced programmers. Some
of these were definitely not Pythonic code for real use.

First question: do you really want to create a new 'very long list' or
modify list 'data' in place. Let's assume the latter.

for i,tup in enumerate(data) :
data[i] = replace(tup)

where replace(tup) is an expression or function that produces a tuple
meeting your criteria. Simplest is
(max(tup[0],Rthresh), max(tup[1],Gthresh), max(tup[2],Bthresh)).

If nearly all your pixels are ok, add the following before the
assignment so you only make replacements when actually needed:
if tup[0] < Rthresh or tup[1] < Gthresh or tup[2] < Bthresh:

Terry Jan Reedy
Jun 27 '08 #5
On Jun 25, 7:26 pm, Terry Reedy <tjre...@udel.e duwrote:
idiolect wrote:
Hi all - Sorry to plague you with another newbie question from a
lurker. Hopefully, this will be simple.
I have a list full of RGB pixel values read from an image. I want to
test each RGB band value per pixel, and set it to something else if it
meets or falls below a certain threshold - i.e., a Red value of 0
would be changed to 50.
I've built my list by using a Python Image Library statement akin to
the following:
data = list(image.getd ata())
Which produces a very long list that looks like [(0,150,175),
(50,175,225),.. .]. I'm trying to figure out a fast and pythonic way
to perform my operation. The closest I've come so far to a succinct
statement is a list comprehension along the syntax of:

Why are you trying to do this with a list comprehension? Learn the
basics first. Perhaps you have read too many of the recent threads
presenting diverting challenges for bored experienced programmers. Some
of these were definitely not Pythonic code for real use.

First question: do you really want to create a new 'very long list' or
modify list 'data' in place. Let's assume the latter.

for i,tup in enumerate(data) :
data[i] = replace(tup)

where replace(tup) is an expression or function that produces a tuple
meeting your criteria. Simplest is
(max(tup[0],Rthresh), max(tup[1],Gthresh), max(tup[2],Bthresh)).

If nearly all your pixels are ok, add the following before the
assignment so you only make replacements when actually needed:
if tup[0] < Rthresh or tup[1] < Gthresh or tup[2] < Bthresh:

Terry Jan Reedy
A giant thank-you to all who've posted in response to my query - these
are all much better approaches to my problem. I think I got hooked on
using a list comprehension as it seemed the most concise approach vs.
other techniques after a bunch of Google searches, but all of you have
pointed out more efficient methods. I appreciate your willingness to
indulge a n00b who hasn't thought his problem through, apparently.
I'll try all of these approaches out over the next day and see what
works best, although I suspect you've all posted sufficient solutions.

Can't wait to try these suggestions out - cheers, idiolect
Jun 27 '08 #6
On Wed, 25 Jun 2008 16:02:52 -0700, John Machin wrote:
Here's one approach (requires Python 2.5 or later):
[(50 if x < 50 else x, 50 if y < 50 else y, 50 if z < 50 else z) for
(x, y, z) in source]
[(max(x, 50), max(y, 50), max(z, 50)) for (x, y, z) in source]

--
09 F9 11 02 9D 74 E3 5B D8 41 56 C5 63 56 88 C0 -- pass it on
Jun 27 '08 #7
idiolect wrote:
On Jun 25, 7:26 pm, Terry Reedy <tjre...@udel.e duwrote:
>idiolect wrote:
Hi all - Sorry to plague you with another newbie question from a
lurker. Hopefully, this will be simple.
I have a list full of RGB pixel values read from an image. I want to
test each RGB band value per pixel, and set it to something else if it
meets or falls below a certain threshold - i.e., a Red value of 0
would be changed to 50.
I've built my list by using a Python Image Library statement akin to
the following:
data = list(image.getd ata())
Which produces a very long list that looks like [(0,150,175),
(50,175,225),.. .]. I'm trying to figure out a fast and pythonic way
to perform my operation. The closest I've come so far to a succinct
statement is a list comprehension along the syntax of:

Why are you trying to do this with a list comprehension? Learn the
basics first. Perhaps you have read too many of the recent threads
presenting diverting challenges for bored experienced programmers. Some
of these were definitely not Pythonic code for real use.

First question: do you really want to create a new 'very long list' or
modify list 'data' in place. Let's assume the latter.

for i,tup in enumerate(data) :
data[i] = replace(tup)

where replace(tup) is an expression or function that produces a tuple
meeting your criteria. Simplest is
(max(tup[0],Rthresh), max(tup[1],Gthresh), max(tup[2],Bthresh)).

If nearly all your pixels are ok, add the following before the
assignment so you only make replacements when actually needed:
if tup[0] < Rthresh or tup[1] < Gthresh or tup[2] < Bthresh:

Terry Jan Reedy

A giant thank-you to all who've posted in response to my query - these
are all much better approaches to my problem. I think I got hooked on
using a list comprehension as it seemed the most concise approach vs.
other techniques after a bunch of Google searches, but all of you have
pointed out more efficient methods. I appreciate your willingness to
indulge a n00b who hasn't thought his problem through, apparently.
I'll try all of these approaches out over the next day and see what
works best, although I suspect you've all posted sufficient solutions.

Can't wait to try these suggestions out - cheers, idiolect
I'd like to emphasize Roger Miller's point with a small example script:

#!/usr/bin/env python
import sys
import Image

def transform_image _getdata(old, new):
image = Image.open(old)

image.putdata([(max(50, r), min(g*2, 255), 0) for r, g, b in
image.getdata()])

image.save(new)

def transform_image _point(old, new):
image = Image.open(old)

transform_red = [max(50, i) for i in range(256)]
transform_green = [min(i*2, 255) for i in range(256)]
transform_blue = [0 for i in range(256)]

image.point(tra nsform_red + transform_green + transform_blue) .save(new)
if __name__ == "__main__":
import os, time
def measure(f):
def g(*args, **kw):
start = time.time()
try:
return f(*args, **kw)
finally:
print f.__name__, time.time() - start
return g

for name in sys.argv[1:]:
a, b = os.path.splitex t(name)
measure(transfo rm_image_getdat a)(name, a + ".getdata" + b)
measure(transfo rm_image_point) (name, a + ".point" + b)

Run it:

$ ./transform_image .py tmp.jpg
transform_image _getdata 27.5557489395
transform_image _point 0.458500862122

For the example Image.point() is about 60 times faster than getdata(). It's
the way to go if you can handle the color channels individually.

Peter
Jun 27 '08 #8

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

Similar topics

39
3161
by: Marco Aschwanden | last post by:
Hi I don't have to talk about the beauty of Python and its clear and readable syntax... but there are a few things that striked me while learning Python. I have collected those thoughts. I am sure there are many discussions on the "problems" mentioned here. But I had this thoughts without looking into any forums or anything... it is kind of feedback.
18
2157
by: Elbert Lev | last post by:
Hi, all! Here is the problem: I have a file, which contains a common dictionary - one word per line (appr. 700KB and 70000 words). I have to read it in memory for future "spell checking" of the words comming from the customer. The file is presorted. So here it goes: lstdict = map(lambda x: x.lower().strip(), file("D:\\CommonDictionary.txt"))
24
3348
by: Mahesh Padmanabhan | last post by:
Hi, When list comprehension was added to the language, I had a lot of trouble understanding it but now that I am familiar with it, I am not sure how I programmed in Python without it. Now I see that generator expressions have been added to the language with 2.4 and I question the need for it. I know that it allows for lazy evaluation which speeds things up for larger lists but why was it necessary to add it instead of improving list...
8
2773
by: Nickolay Kolev | last post by:
Hi all, I have a list whose length is a multiple of 3. I want to get a list of tuples each of which has 3 consecutive elements from the original list, thus packing the list into smaller packets. Like this: l = tups =
105
5319
by: Christoph Zwerschke | last post by:
Sometimes I find myself stumbling over Python issues which have to do with what I perceive as a lack of orthogonality. For instance, I just wanted to use the index() method on a tuple which does not work. It only works on lists and strings, for no obvious reason. Why not on all sequence types? Or, another example, the index() method has start and end parameters for lists and strings. The count() method also has start and end parameters...
3
3118
by: Gerard Brunick | last post by:
My way is ugly. These has to be a better way. Thanks, Gerard
11
16792
by: Noah | last post by:
I have a list of tuples I want to reverse the order of the elements inside the tuples. I know I could do this long-form: q = y = for i in y: t=list(t)
10
5151
by: rshepard | last post by:
While working with lists of tuples is probably very common, none of my five Python books or a Google search tell me how to refer to specific items in each tuple. I find references to sorting a list of tuples, but not extracting tuples based on their content. In my case, I have a list of 9 tuples. Each tuple has 30 items. The first two items are 3-character strings, the remaining 28 itmes are floats. I want to create a new list from...
25
4090
by: beginner | last post by:
Hi, I am wondering how do I 'flatten' a list or a tuple? For example, I'd like to transform or ] to . Another question is how do I pass a tuple or list of all the aurgements of a function to the function. For example, I have all the arguments of a function in a tuple a=(1,2,3). Then I want to pass each item in the tuple to a function f so that I make a function call f(1,2,3). In perl it is a given, but in python, I haven't figured out
0
8795
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8701
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
7941
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
6620
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 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 a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
4459
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
4714
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
3154
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
2509
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2101
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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.