Lecture 7 — Tuples, Modules, Images

Overview

  • Material for this lecture is drawn from Chapter 4 of Practical Programming.

  • We will first learn a simple data type called tuples which simplify some things (like returning multiple values).

  • We will then revisit modules, how functions you write can be used in other programs.

  • Most of the class we will learning how to use a new module for manipulating Images.

    • We will introduces a new data: image (much more complex than the other data types we have learnt so far)

    • A module specifically designed for this data type (PILLOW).

      Note: We will NOT use the media module discussed in the text, opting instead for the more widely-used PILLOW (Python Imaging Library), comprised of multiple modules.

Tuple Data Type

  • A tuple is a simple data type that puts together multiple values as a single unit.

  • The main advantage is that you can access individual elements in a tuple: first value starts at zero (this is a big Computer Science thing!)

    >>> x = (4, 5, 10)   # note the parentheses
    >>> print x[0]
    4
    >>> print x[2]
    10
    >>> len(x)
    3
    
  • Actually, tuples and strings are very similar in many ways. We will explore them in class.

    >>> s = 'abc'
    >>> s[0]
    'a'
    >>> s[1]
    'b'
    
  • Two important points: for tuples and strings, you cannot change a part of the tuple. Only the whole tuple!

    >>> x[1] = 2
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    TypeError: 'tuple' object does not support item assignment
    >>> s[1] = 'A'
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    TypeError: 'str' object does not support item assignment
    

What are tuples good for?

  • Tuples are Python’s way of making multiple assignments.

    >>> 2,3
    (2, 3)
    >>> x = 2,3
    >>> x
    (2, 3)
    >>> a,b=x
    >>> a
    2
    >>> b
    3
    >>> c,d=3,4
    
  • You can write functions that return multiple values.

    def next_population(bpop, fpop):
        bpop_next = (10*bpop)/(1+0.1*bpop) - 0.05*bpop*fpop
        bpop_next = int( max(0,bpop_next) )
        fpop_next = 0.4 * fpop + 0.02 * fpop * bpop
        fpop_next = int( max(0,fpop_next) )
        return bpop_next, fpop_next
    
    b = 100
    f = 5
    
    bnext, fnext = next_population(b,f)
    print bnext, fnext
    

Example 1: Finding distance between two points

  • Write a function that takes as input two tuples representing points: (x,y) and returns the distance between them.

Basics of modules

  • Recall that a collection of Python variables, functions and objects, all stored in a file

  • Modules allow code to be shared across many different programs.

  • Before we can use a module, we need to import it:

    >>> import module_name
    >>> module_name.function()
    
  • We will see an example class of using code that we have written as a module in another program.

PIL/PILLOW — Python Image Library

  • PILLOW is a series of modules built around the Image type, our first object type that is not part of the main Python language

    • We have to tell Python about this type through import
  • We will use images as a continuing example of what can be done in programming beyond numbers and beyond text.

  • See

    http://pillow.readthedocs.org/en/latest/handbook/tutorial.html

    for more details.

Images

  • An image is a two-dimensional matrix of pixel values

  • The origin is in the upper left corner, see below:

    ../_images/image_premier.png
  • Pixel values stored in an image can be:

    • RGB — a “three-tuple” consisting of the red, green and blue values, all non-negative integers
    • L — a single “gray-scale” integer value representing the brightness of each pixel
  • Some basic colors:

    Color (red,green,blue) value
    Black (0,0,0)
    Red (255,0,0)
    Green (0,255,0)
    Blue (0,0,255)
    White (255,255,255)
    Light Gray (122,122,122)

Some important image modules

  • Image module contains main functions to manipulate images: open, save, resize, crop, paste, create new images, change pixels, etc.
  • ImageDraw module contains functions to touch up images by adding text to it, draw ellipses, rectangles, etc.
  • ImageFont contains functions to create images of text for a specific font.
  • We will only use the Image module in this lecture.

Image Type and Methods

  • Let us now see some very useful image methods

  • im = Image.open(filename) reads an image with the given filename

    and returns an image object (which we are storing in the variable im). It assumes the file is stored in the same directory as your script.

  • im.show() displays the image

  • im.save(filename) saves the image to the given file

  • Images are complex objects. They have associated properties that you can print or use:

    >>> im = Image.open('swarm1.jpg')
    >>> im.size
    (600, 800)
    >>> im.format
    'JPEG'
    >>> im.mode
    'RGB'
    >>> im.show()
    

    You can see that im.format and im.mode are strings, while im.size is a tuple.

  • You can create an empty new image with given dimensions using: Image.new("RGB",(width,height)).

    >>> im5 = Image.new('RGB', (200,200))
    >>> im5.show()
    
  • You can also create a new image by cropping a part of a given image:

    >>> im.crop((w1,h1,w2,h2))
    

    which will crop a box from upper left corner (w1, h1) to lower right corner (w2,h2). You can see that the box is entered as a tuple. Try this:

    >>> im2 = im.crop((100,100,300,400))
    >>> im2.show()
    >>> im.show()
    
  • You can resize an image and get a new image. The new size must be given as a tuple: im.resize((width,height))

    >>> im3 = im.resize((300,200))
    >>> im3.save('resized.jpg')
    
  • im.convert(mode) changes the mode of an image ('L' is black and white)

    >>> im4 = im.convert('L')
    >>> im4.show()
    

Our First Image Program

from PIL import Image

filename = "chipmunk.jpg"
im = Image.open(filename)
print '\n' '********************'
print "Here's the information about", filename
print im.format, im.size, im.mode

gray_im = im.convert('L')
scaled = gray_im.resize( (128,128) )
print "After converting to gray scale and resizing,"
print "the image information has changed to"
print scaled.format, scaled.size, scaled.mode

scaled.show()
scaled.save(filename + "_scaled.jpg")

Something new, functions that change an image

  • All functions we have seen so far return a new result, but never change the object that they apply to.

  • We will see that this is not true for more complex objects and containers. This is mostly for efficiency reason.

  • You just have to remember how each function works. For now, images are the only objects with this property.

  • Here is our first function with this property: im.paste(im2, (x,y)) pastes one image (im2) into the first image (im1) starting at the top left coordinates (x,y).

    Note that the second image must fit in the first image starting with these coordinates.

  • How we call such a function is different:

    >>> im1 = Image.open('sheep.jpg')
    >>> im1.size
    (600, 396)
    >>> im = Image.new('RGB', (600, 396*2))
    >>> im.paste( im1, (0,0))
    >>> im.show()
    >>> im.paste( im1, (0, 396))
    >>> im.show()
    
  • The fact that the function paste changes an image is an implementation decision made by the designers of PIL, mostly because images are so large and copying is therefore time consuming.

    Later in the semester, we will learn how to write such functions.

Example 2: Cut and pasting parts of an image

  • This example crops three boxes from an image, creates a new image and pastes the boxes at different locations of this new image.

    import Image
    
    im = Image.open("lego_movie.jpg")
    w,h = im.size
    
    # Crop out three columns from the image
    ## Note: the crop function returns a new image
    part1 = im.crop((0,0,w/3,h))
    part2 = im.crop((w/3,0,2*w/3,h))
    part3 = im.crop((2*w/3,0,w,h))
    
    ## Create a new image
    newim = Image.new("RGB",(w,h))
    ## Paste the image in different order
    ## Note: the paste function changes the image it is applied to
    newim.paste(part3, (0,0))
    newim.paste(part1, (w/3,0))
    newim.paste(part2, (2*w/3,0))
    newim.show()
    

Summary

  • Tuples are similar to strings and numbers in many ways. You cannot change a part of a tuple. However, unlike other simple data types, tuples allow access to the individual components using the list notation.
  • Modules contain a combination of functions, variables, object definitions, and other code, all designed for use in other Python programs and modules
  • PILLOW provides a set of modules that define the Image object type and associated methods.

Studying for the exam

Let us try to make a list of the crucial things to review before the exam.

  • Syntax: can you find syntax errors in code?

  • Correct variable names, assigning a value to a variable

  • Output: can you compute the output of a piece of code?

  • Expressions: operator precedence

  • The distinction between integer and float division

  • The distinction between division (4/5) and modulo (4%5) operators, and how they work for positive and negative numbers

  • Remember shorthands: +=, -=, /=, *=.

  • Functions: defining functions and using them

  • Distinguish between variables local to functions and variables that are global

  • Modules: how to import and call functions that are from a specific module (math is the only one we learnt so far)

  • How to access variable values defined in a module (see math.pi for example)

  • Strings: how to create them, how to escape characters, multi-line strings

  • How to use raw_input(): remember it always returns a string

  • Boolean data type: distinguish between expressions that return integer/float/string/Boolean

  • Remember the distinction between = and ==

  • Boolean value of conditions involving AND/OR/NOT

  • IF/ELIF/ELSE statements, how to write them. Understand what parts are optional and how they work

  • Creating, indexing and using tuples

  • Remember the same function may work differently and do different things when applied to a different data type

  • Review all about the different ways to call the print function for multiple line of input

     name = 'Eric Cartman'
     age = 8
     location = 'South Park'
    
     print "Option 1: Student name:", name, 'lives at:', location
     print "Student age:", age
     print
    
     print "Option 2: Student name:", name, 'lives at:', location, "\nStudent age:", age
     print
    
     print "Option 3: Student name: %s lives at: %s Student age: %d" %(name, location, age)
     print
    
    Try and see whether you can predict the output.
    

Now, let’s review all the functions we have learnt in this class.

  • + (concatenation and addition), * (replication and multiplication), /, %, **
  • int(), float(), str(), math.sqrt(), min(), max(), abs(), round(), sum(), string.upper(), string.lower(), string.replace(), string.capitalize(), string.title(), string.find(), string.count(), len()
  • Can you tell which data types each apply to and how?
  • Distinguish between the different types of functions we have learnt in this class:
  • Functions that take one or more values as input and return something (input objects/values are not modified)
>>> min(3,2,1)
1
>>> mystr = 'Monty Python'
>>> len(mystr)
12
  • Functions that take one or more values as input and return nothing (input objects/values are not modified)
>>> def print_max(val1, val2):
...     print "Maximum value is", max(val1, val2)
...
>>> x1 = 10
>>> x2 = 15
>>> print_max(x1, x2)
Maximum value is 15
  • Functions that apply to an object, like a string, and return a value (but not modify the object that they apply to)
>>> mystr = 'Monty Python'
>>> mystr.replace('o','x')
'Mxnty Pythxn'
>>> mystr
'Monty Python'
>>> mystr.upper()
'MONTY PYTHON'
>>> mystr
'Monty Python'
  • Functions that apply to an object, like an Image and modify it (but not return anything), we only learn Image.paste so far.
>>> im.paste( im2, (0,0) )
  • Local vs. global variables: Can you guess what each of the print statements print and explain why?

    def f1(x,y):
        return x+y
    
    def f2(x):
        return x+y
    
    x = 5
    y = 10
    
    print 'A:', f1(x,y)
    print 'B:', f1(y,x)
    print 'C:', f2(x)
    print 'D:', f2(y)
    print 'E:', f1(x)