MCS-177 Project 7: Image Processing (Spring 2010)

Overview

In this project, you will learn how a computer can modify images. You will be programming transformations similar to those built into programs like Photoshop.

You are to do this project using pair programming, unless you have requested to work alone and I have approved that request. I will assign partners for the pair programming. If you and your partner are not in agreement regarding doing extra credit work, you can also submit supplemental extra credit problems individually.

Specific tasks

  1. Download image.py and Liskov.gif. You should put them in the same folder with each other. The file image.py contains a combination of the textbook's Listings 6.1, 6.3, 6.5, and 6.6 (pages 194-204) and will serve as the starting point for your work. The file Liskov.gif is a sample image for you to use in testing your program. It is a photo of Barbara Liskov taken by Donna Coveney of MIT and reproduced here with MIT's permission.

  2. Open image.py in Idle, run it, and and in the Python Shell window enter

    generalTransform("Liskov.gif")
    

    This should open up two new windows. One, the "Console", you can ignore. The one you should look at is titled "Image Processing". It should contain two pictures of Barbara Liskov, one in color and the other that has been turned into grayscale. If you click within this window (rather than on its title bar), the window will close and the generalTransform procedure will return to the Python Shell.

  3. The name "Image Processing" isn't a very helpful title for the window. Change generalTransform so that it uses whatever the name of the image file is as the title of the window. Thus, in the particular example shown above, the window would wind up titled "Liskov.gif".

  4. The window currently always is 600 pixels wide by 200 pixels high. That would be almost the right size if the image being processed was 300 pixels wide by 200 pixels high. The window would then be the right size for two versions of the image, but it wouldn't allow any space for the blank pixel between the two. Moreover, the image you are working with is a different size, as indeed most images are. Change generalTransform so it calculates the window's width and height based on the image's width and height. You might also want to test using portrait.gif and/or landscape.gif.

  5. The name generalTransform suggests that this procedure ought to be able to do other transformations, not just grayscale. To achieve this objective, modify the procedure to have a second parameter, the pixel transformation function to use. Whatever function is passed in ought to be passed along to pixelMapper, rather than grayPixel always being used. You ought to be able to get the grayscale and negative versions of the image (each time along with the original) by evaluating the following two expressions. (Warning: the negative version isn't the most flattering.):

    generalTransform("Liskov.gif", grayPixel)
    generalTransform("Liskov.gif", negativePixel)
    
  6. Now it is time for you to write your own pixel transformation function, which you should try out the same way as grayPixel and negativePixel. Do Exercise 6.17 (on page 204), which calls for writing a pixel function for sepia toning. Regarding the hint in that exercise, first think about how you would convert the RGB values to integers. Then think about how you would make sure each value is no larger than 255, using the min function.

  7. Finally, you should write one image transformation that cannot be performed by generalTransform because it moves the pixels around, rather than transforming the R, G, and B values within each individual pixel. Do Exercise 6.32 (on page 225), which calls for you to write a rotateImage90 procedure. The textbook's specification doesn't indicate which direction you should rotate the image; let's settle on clockwise, so that Barbara Liskov's head points to the right. The rotateImage90 procedure transforms an image into an image and so is somewhat analogous to pixelMapper, although unlike pixelMapper it only has a single parameter, the image to transform. (Note that I really do mean an image, not the name of a file that contains the image.) The rotateImage90 procedure should return the rotated image as its result, without actually displaying anything.

    In order to show the result, you should also write a procedure analogous to generalTransform (but with just one parameter, the image file's name) which reads in an image file, produces a window the correct size to hold both the original image and the rotated version, uses rotateImage90 to produce the rotated image, and displays both images in the window.

    Some issues to think about: what will be the width and height of the rotated image? What should the width and height of the window be? How do row and column numbers in the rotated image correspond to row and column numbers in the original image?

    When you test your procedure, be sure to look closely at the images that are displayed to check that the rotation worked correctly. In particular, make sure you didn't accidentally flip the image as well as rotating it. Also, make sure you didn't accidentally clip off any edge of the image. You might also want to test using portrait.gif and/or landscape.gif.

  8. Having seen Barbara Liskov in various colorings (flattering and otherwise) and tipped on her side, it is time for you to figure out who she is. The photo you've been working with was included in a press release when she won a major award in March of 2009. Do a web search to find out what that award was and a few other facts about her. Write a few English sentences in which you include the name of the award, some descriptive information about the award, and at least two other facts about her.

Extra credit opportunities

The first four extensions to the project are independent of each other. You can do any of them, or can do more than one of them in any order. The fifth extension should only be done if you have done the third. The sixth extension should only be done if you have done the fifth.

  1. You can write another pixel transformation procedure for use with generalTransform, this one for "posterization" of an image. Posterizing the image means converting it to use comparatively few colors. Large areas of pixels may wind up all having the exact same color after posterization, creating a flat impression, whereas in the original image, they have subtly varying colors, providing shading. One comparatively simple approach to posterization treats the R, G, and B values independently of each other. For each of the three colors, the original image contains a value in the range from 0 to 255. If that value is is in the range from 0 to 63, you can round it to 32. Similarly, you can round any value that is in the range from 64 to 127 to 96. Continuing in this way, you can convert the R, G, or B value from being any of 256 possibilities to being one of just 4 different possibilities, each one representing one of 4 broad bands. You are also welcome to experiment with any other form of posterization.

  2. Write a sentence in which you describe at least one painting from the Elmyr de Hory exhibit at the Hillstrom Museum (through April 18) that uses large areas of relatively flat color, somewhat similar to the result of the posterization transformation described in the previous extra credit opportunity. For each painting you mention, your description should identify the painting and the artist whose style it is in.

  3. Do Exercise 6.29 (on page 224), in which you form a precisely symmetrical image by mirroring the pixels from the left half of the original image so that they appear on both sides of the transformed image, equally far from the center line. As with the rotation exercise, you should write one procedure that does the image transformation and a second procedure that reads an image file in and displays the original and transformed images side by side in a window.

  4. Do Exercise 6.23 (on page 222), in which you scale an image up by replicating each pixel a specified number of times in the horizontal direction and a (perhaps different) specified number of times in the vertical direction. You can assume that these scaling factors will both be positive integers. As with the rotation exercise, you should write one procedure that does the image transformation and a second procedure that reads an image file in and displays the original and transformed images side by side in a window.

  5. If you chose to do mirroring, you had to write a procedure for reading in an image file, transforming the image, and displaying the original and transformed images side by side in a window. This procedure is nearly identical to one you wrote for showing rotated images. Write one more general procedure named showTransform that can serve for both of these cases. It should take two parameters. One is the name of the image file. The other is the name of the image transformation procedure. For example, you could evaluate showTransform("Liskov.gif",rotateImage90).

  6. The previous extra-credit option indicated how one general showTransform procedure can show an image along with a transformed version of the image, whether the transformation is rotation or mirroring. But what about other transformations: grayscale, negative, sepia tone, and posterization (if you did it)? All of those are handled through generalTransform, which should look very similar to your showTransform procedure. In order to put generalTranform out of business, write a makePixelMapper procedure so that (for example) showTransform("Liskov.gif",makePixelMapper(grayPixel)) takes the place of generalTransform("Liskov.gif",grayPixel). This should work for any pixel transformation procedure, not just grayPixel and the others that have already been written. Or, if you have done scaling, you could similarly write a makeScaler procedure so that (for example) showTransform("Liskov.gif",makeScaler(2,2)) displays original and double-sized vesions of the picture.

Submitting your work

For this project, you should copy and paste the code of each procedure you have modified or newly written directly into an email message that you send to max@gustavus.edu. Do not include any procedures that you used without change. Your email should also contain the information you found about Barbara Liskov. If you want the extra-credit point for answering the question about the Hillstrom Museum's exhibit, you should include that answer in your email as well.

Grading

You will earn one point for each of the following accomplishments (with those after 20 being extra credit):

  1. Your generalTransform procedure uses the image filename as the title for the window.

  2. Your generalTransform procedure uses an appropriate width for the window.

  3. Your generalTransform procedure uses an appropriate height for the window.

  4. Your generalTransform procedure works with any pixel transformation procedure.

  5. Your sepia toning transformation has the correct general structure for a pixel transformation.

  6. Your sepia toning transformation correctly uses the formulas given in the textbook.

  7. Your sepia toning transformation ensures that the R, G, and B values it produces are integers.

  8. Your sepia toning transformation limits the R, G, and B values it produces to the correct range.

  9. Your sepia toning transformation is not unnecessarily complex and uses descriptive names.

  10. Your rotateImage90 procedure produces an image of the correct width.

  11. Your rotateImage90 procedure produces an image of the correct height.

  12. Your rotateImage90 procedure copies each original pixel into exactly one location in the result image.

  13. Your rotateImage90 procedure positions each copied pixel in the correct row.

  14. Your rotateImage90 procedure positions each copied pixel in the correct column.

  15. Your rotateImage90 procedure is not unnecessarily complex and uses descriptive names.

  16. You wrote an appropriate procedure to show the result of rotateImage90 along with the original image.

  17. You wrote an English sentence that provides the name of the award Barbara Liskov received in 2009.

  18. You wrote one or more English sentences that describe the award Barbara Liskov received in 2009.

  19. You wrote one or more English sentences that provide an additional fact about Barbara Liskov.

  20. You wrote one or more English sentences that provide a second additional fact about Barbara Liskov.

  21. You wrote a correct pixel transformation for posterization.

  22. You identified at least one painting from the Elmyr de Hory exhibit that uses color in a way similar to posterization, indicating also the name of the artist in whose style it is.

  23. Your procedure for mirroring an image produces an image of the correct width and height.

  24. Your procedure for mirroring an image copies each result pixel from the appropriate location in the original.

  25. Your procedure for enlarging an image produces an image of the correct width and height.

  26. Your procedure for enlarging an image copies each result pixel from the appropriate location in the original.

  27. Your showTransform procedure makes a window the appropriate width and height.

  28. Your showTransform procedure displays the correct images without unnecessary complexity.

  29. Your makePixelMapper or makeScaler procedure works correctly for an arbitrary pixel transformation procedure or arbitrary scaling factors, respectively.

  30. Your makePixelMapper or makeScaler procedure is not unnecessarily complex and uses descriptive names.