Welcome to Maine
CS 151: Computational Thinking
(Spring 2014)

Syllabus

Teachers
Beatrice
Caitlin
Stephen
Dan
Lanya
Victoria
Matt
Hieu
Jacob
Scott
Hieu


Assignments


Other Pages

Project 4:
The Warhol Project


Assigned: Wed Feb 26 2014
Due: 11:59:59 PM on Tue Mar 04 2014
Team Size: 1
Language: Python


Lab:

The main purpose of this lab is to give you the tools you need to complete an image-manipulation project.

Tasks

  1. In your personal file space, make a folder called Proj4. Then download the following files to it.
  2. Open a text editor (e.g TextWrangler). Create a new file called show.py. Put the standard docstring at the top of the file with your name, date, and file name. Save it in your Proj4 folder.
  3. After the docstring, write the command to tell Python to import the graphics package, the display package, and the sys package:

    import graphics
    import display
    import sys

  4. Save the image of yourself that Dale emailed to you. You are also welcome to use any of the following images.
  5. The first thing we're going to do is create a simple program that will read in an image and display it in a window. We'll use the command line to specify which image to view.

    Create a main function in your show.py file. When coding, it's important that sys.argv is only used in the very top level of code. Thus, give your main function one parameter, commandLineStrings. When you call main, that will be the list of strings the user typed on the command line. The main function should do the following.

    1. Test if there are at least two strings from the command line. If not, print a usage message and exit using the exit() function. Use the len() function to test how many strings there are in the parameter.
    2. Load the file specified in the second string of commandLineStrings as a Pixmap. You can do this by calling the function graphics.Pixmap() with the filename as the argument and assigning the result to a variable. Therefore, you need a variable on the left side of an assignment and the graphics.Pixmap call on the right. You need to pass the filename to the Pixmap function. The filename will be the second element in the list of strings from the command line.
    3. Use the displayPixmap function in the display package to create a window and display the Pixmap. You went over this function in class. It takes two arguments, which are the Pixmap to display and the title. Use the filename as the title of the window. The displayPixmap function returns a window reference, which you need to assign to a variable. That means the variable to hold the window reference must be on the left side of an assignment and the function call must be on the right.
    4. Finally, call the getMouse method of the window. That means you type the name of the variable holding the window reference, then .getMouse() to call the method. This will wait for a mouse click in the window and then go on to the next instruction. If there is no next instruction, the program will terminate.

    Below the main function, put a conditional call to it, using the method we learned last week. Pass the main function the list sys.argv.

    if __name__ == "__main__":
        main(sys.argv)
    

    Once complete, try out your show function.

  6. The second thing we're going to do in lab is figure out how to manipulate pixels in an image. Each pixel in a color image has three values (r, g, b). Each pixel is addressed by its row and column. There are rows x columns pixels in an image. The Zelle graphics library (graphics.py) contains two functions that make it easy to get and set pixels if you have a Pixmap object. The three lines below demonstrate how you would read in a Pixmap from a file (which we did above) and then swap the red and blue channels of pixel 42 (x), 35 (y).
        pixmap = graphics.Pixmap( 'mypixmap.ppm' )
        (r, g, b) = pixmap.getPixel( 42, 35 )
        pixmap.setPixel( 42, 35, (b, g, r ) )
    
  7. Create a new file called filter.py. Do the usual stuff of putting your name, date, and file name at the top. Then import graphics and sys. Save it in your Proj4 directory.
  8. Create a function named something like swapRedBlue that takes in one argument, which will be a Pixmap object. The algorithm is written below as comments, properly indented. Read through them and make sure you understand the process. Then fill in the python code.
    def swapRedBlue( pixmap ):
        # loop over each row rowIndex
            # loop over each column columnIndex
                # get the r, g, b values of the pixel indexed by (columnIndex, rowIndex)
                # set the pixel indexed by (columnIndex, rowIndex)  to the value (b, g, r)
        # return
    
  9. Create a test function in your filter.py file that takes in an argument which is the list of strings from the command line. As above, first test if there are enough arguments and print out a usage statement and exit if there are not. If there are enough arguments, then open the image and store the result in a variable. Pass the Pixmap to the swapRedBlue function, then save the result to a file. If your pixmap variable were pixmap, then you could save it by using

    pixmap.save('myfilename.ppm')

    You can pass whatever filename name you want to the save function. I recommend not having spaces in the name.

    At the end of your filter.py file, put a call to your test function behind a conditional that tests the value of the __name__ variable, as we did last week.

    if __name__ == "__main__":
        test( sys.argv )
    

    When you are done, run your filter.py program, giving it an image filename as the argument. Then look at the result with your show program. Now, perhaps, you see why command line parameters are useful beasts.


Assignment:

The purpose of this project is to make a collection of images in the style of Andy Warhol. You'll do this by manipulating the pixel colors of an image.


Tasks

Make sure you have copies of the graphics.py and display.py files.

For this assignment you're going to create two python programs. One will generate a Warhol style collage. The other will change the blue screen to a different color. Both will write their results to an image file, which you can then view with your show program.

  1. In your filter.py file, create a function putPixmap which takes four arguments. The first argument will be a destination Pixmap, the second argument will be a source Pixmap, and the last two arguments will be an x, y location to place the second Pixmap into the first. The function outline in comments is given below.

    For each comment inside the function below, you need to write one line of python code.

    # place source into destination upper left at x, y in destination
    def putPixmap( destination, source, x, y ):
        # loop over each row, i, in source
            # loop over each column, j, in source
                # from source, get the (r, g, b) value at pixel (j, i)
                # in destination, set location (x + j, y + i) to (r, g, b)
    

    Once you have written your function, you can use this file to test it. Run the test program on the command line and give it an image filename as its argument. For example:

    python testPutPixmap.py miller.ppm

    Remember that the Zelle graphics package can read only PPM type images.

    Once you are confident about the code, remove the comments that we supplied. Because they simply describe each line of code, they don't help the reader understand the overall purpose of the code. Helpful comments include the docstring (which you need to write), which explains the meaning of each parameter. If you find them helpful because they remind you how to code up our instructions, then you may leave them there. But don't assume your code is well-commented because you copied our comments.

  2. Create three more functions like swapRedBlue that edit the colors in a Pixmap to achieve some effect. See if you can emulate some of the Instagram effects.
  3. Create a new script, warhol.py, for your main program. It will read in one image, create four copies of it, use your manipulation functions to change their colors, create a new blank image that is width*2 by height*2 and then use the putPixmap function to insert the four edited images. Finally, it should write out the collage image.
    def main(commandLineStrings):
        # if the length of commandLineStrings is less than 2
            # print a usage statement
            # exit
    
        # read in the Pixmap from commandLineStrings[1], put the result into a variable (e.g. pixmap)
        # clone pixmap and assign it to a new variable (e.g. map1)
        # clone pixmap and assign it to a new variable (e.g. map2)
        # clone pixmap and assign it to a new variable (e.g. map3)
        # clone pixmap and assign it to a new variable (e.g. map4)
    
        # call your first manipulator function on map1
        # call your second manipulator function on map2
        # call your third manipulator function on map3
        # call your fourth manipulator function on map4
    
        # create a new Pixmap that is 2*width x 2*height and store it in a new variable
    
        # put map1 into the collage at (x, y) = (0, 0)
        # put map2 into the collage at (0, height)
        # put map3 into the collage at (width, 0)
        # put map4 into the collage at (width, height)
    
        # save the big map to a file
    
    

    Finish up this task by putting a call to main inside the conditional statement we've used before. Then call your python program and view the collage.

    Tip: For this function, helpful comments would indicate the different sections of code (e.g. "read in one pixmap", "make 4 copies of it", "make an empty pixmap big enough to hold 4 copies of this one", and "put the 4 filtered images into the big one"). And, of course, a docstring is a must.

    Important: You'll want to add the pictures to your writeup, but the wiki doesn't support the .ppm format. There are two ways to get around this problem. The first is to take a screenshot like we've done in the past and upload that instead.

    Alternatively, you can use some cool image-manipulation software installed on the lab machines. (Sadly, it isn't automatically built into Mac OS X the same way python is.) To do this, use convert at the command line like so:

    $ convert myImage.ppm myImage.png

    You can even resize it this way:

    $ convert myImage.ppm -scale 25% mySmallerImage.png

    More information about convert is available at the ImageMagick web site.

  4. Your last task is to create a python program that reads in your blue-screen image and turns the blue-screen pixels to a different color. The rest of the pixels should remain untouched. You will need to loop over each pixel in the image and test if it is very blue. If it is very blue, change its color. Otherwise, leave it alone.

    A reasonable test for 'very blue' is if the blue channel is at least twice the red channel and also bigger than the green channel.


Extensions

  • Create a larger or more complex Warhol style collage. Place the images in a pattern more complicated than that of a square (but not random!).
  • Do something more interesting than a single color to replace the blue screen.
  • Place yourself in a scene. Start with a background scene that is the same size image as your blue-screen image. Then copy only non-blue pixels from your images into the background. You can do this by making a version of putPixmap that copies only non-blue pixels. You could call it putPixmapWithoutBlue.
  • Enable your Warhol program to read in multiple images from the command line and make a collage for each one, or a collage that integrates several images.
  • Make a function or functions that modify the image based on one or more parameters and demonstrate that you can make several different output images by varying the parameter.
  • Use a Python language feature new to you (not just a new library feature or function)

Writeup and Hand-In

Before handing in your code, double check that it is well-styled:

  • All file names use the case we requested.
  • All variable names and function names use either camelCase or snake_case.
  • All functions and files have docstrings. (One nice way to check this is to generate the documentation webpages and see that they contain everything.)
  • Comments are added to explain complicated code blocks.
  • All variable and function names are appropriately descriptive.
  • Functions are defined before any other code is added at the top level of each file.
  • Top level code is wrapped so that it won't execute if that file is imported by another.

Make a new wiki page for your assignment. Put the label cs151s14project4 on the page. Each of you needs to make your own writeup.

In addition to making the wiki page writeup, put the python files you wrote on the Academics server in your private handin directory.

Colby Wiki

In general, your writeup should follow the outline below.

  • A brief summary of the task, in your own words. This should be no more than a few sentences. Give the reader context and identify the key purpose of the assignment.
  • A description of your solution to the tasks, including any images you created. (Make sure your images are appropriately sized to fit onto the wiki page.) This should be a description of the form and functionality of your final code. You may want to incorporate code snippets in your description to point out relevant features. Note any unique computational solutions you developed.
  • A description of any extensions you undertook, including images demonstrating those extensions. If you added any modules, functions, or other design components, note their structure and the algorithms you used.
  • A brief description (1-3 sentences) of what you learned.
  • A list of people you worked with, including students who took the course in previous semesters, TAs, and professors. Include in this list anyone whose code you may have seen. If you didn't work with anyone, please say so.
  • Don't forget to label your writeup so that it is easy for others to find. For this lab, use cs151s14project4