Compsci 101, Fall 2014, Lab 8

For this lab you'll think about enumerate, and odds with cards. You'll also revisit images and process them in a different way, and also find hidden images.

The lab

In this lab you will:

There is code to snarf for lab 8.

Getting Credit for Lab 8

To get credit for this lab, you will need to enter your names and netids, and the answers to several questions on an online form.

Complete this form for credit for lab 8

(the same questions are accessible here as well).

Part 1: Enumerate

Consider the following code that uses enumerate to return a list of the pairs of the index and item from a list.
def listOfTuples(alist):
# returns a list of the enumerated tuples of (index,item)
    returnList = []
    for (index,item) in enumerate(alist):
        returnList.append((index,item))
    return returnList

names = ['Fred', 'John', 'Sue']
print listOfTuples(names)

Output:
[(0, 'Fred'), (1, 'John'), (2, 'Sue')]
Rewrite the code without enumerate and with one line that uses a list comprehension.


Part 2: Image Processing again


The most famous professional-grade image modification program is Photoshop, and images are often "photoshopped" to enhance certain properties. This photo was released by the Iranian government in 2008 to display the power of their new missiles, and they photoshopped it so that the missile launch appeared larger.

Image courtesy of Little Green Footballs.

In this lab we will revisit Images and process them in a slightly different way. In the last lab with images we always returned a single integer. In this lab we will return a pixel (a tuple of three RGB values).

Remember that Images are a powerful way of conveying information and computers give us powerful way of modifying images. This lab involves manipulating pixmaps by transforming each color in the original pixmap using the same algorithm (such as darkening, inverting, posterizing, coverting it to grey scale). Your program will then perform several operations on these images to acheive a larger effect.

Remember that images are stored by computers in a variety of formats, such as GIF, JPG/JPGEG, TIFF, and PNG. These formats differ in how faithfully they represent the original picture, how well they can be compressed to reduce the space each image takes up, or how well they can be copied from one type of computer to another. However, no matter what format the image is stored in, it can always be represented as a mapping of (x, y) pixel position to a color (the range of colors may be restricted to values of grey or just black and white). Thus, for the remainder of this project, we will refer to all formats of digital images as images.

This week's lab revisits the Python Imaging Library (PIL) which provides a simple interface for processing images. We will create basic color filters (RGB color model) that can be applied to images then combine them to create larger effects.

TinEye is a search engine whose queries are images and whose search results are places that this image can be found. When you get a chance, experiment with it to try to figure out how it works. Can the search results be different file formats than your query (e.g., JPEG vs. GIF)? How much detail/quality can you leave out of the image without throwing off the results?

Start by snarfing the Lab 8 code from the class website. Alternatively, you can browse code here .

In this lab we will be using a few functions from Python's Image library (shown in the code snippet below). This code opens an image, displays the image, gets all RGB pixel values from the image, sets each pixel's red value to zero, and then displays the image again.

img = Image.open("vases.png") img.show() pixels = [(0,b,g) for (r,g,b) in img.getdata()] img.putdata(pixels) img.show()

The images displayed are shown below, unaltered on the left, no red on the right.

The image above is included in your snarf files. If you accidentally overwrite the original with a transformation, you can re-download the image here. It depicts custom made vases from Tsuga Studios

Image Methods

Here's a brief summary of the Image methods we will use in this lab (although PIL provides many more).

In the first part of the lab you'll write several filter functions. Each one takes a single (R,G,B) tuple, changes the values or R, or G, or B (or all of them or none of them) and returns a new (R,G,B) tuple. See the explanation below.

The code for this part of the lab is only in one Python module, ImageProcessing.py.

NOTES1: Changing file names and transformations

When ImageProcessing.py runs, there are two lines at the bottom of the file you will want to change to see different results.

These two lines:

input_file = "duke_Logo.png"
load_and_go(input_file, invert)

The first one you will want to change the image to another image at some point. There are several images with the snarf, including different types of images.

The second line you will need to change the transformation you are testing. The default is "invert" which has already been implemented.

NOTE2: For those on a PC with Windows 7 OR IF YOU GET ANY STRANGE ERRORS WHEN RUNNING THIS PROGRAM

If you are on a PC with Windows 7 (and possibly others might also have this problem), you will see errors when it tries to display the image through the program. That's ok, the transformation will modify the file processedImage.jpg.

To see the resulting transformation you just need to click on processedImage.jpg to see the change. You may have to refresh the project folder in Eclipse the first time you run the program to see this file.

Image Filters

We have started by developing a framework for image filters in Python in the module ImageProcessing. It works by applying the filters you write to each pixel of the image. You should implement each of the following filters: test each one, see if the image looks like the altered blue-devil.

Invert. Create a photographic negative of the image by inverting each of the three RGB channels of the pixel. For example, if the pixel has the values (255, 0, 128) for its red, green, and blue channels, respectively; then the resulting color should have the values (0, 255, 127). In other words, each value is the other's opposite within the range of possible values from 0 .. 255. Thus, if this operation is performed on an image twice in succession, the image would appear unchanged.
Darken. Darken the image by reducing the values of each of the three RGB channels of the pixel by 10% of their original value. Be careful not to produce a color value outside the range of possible values from 0 .. 255. Don't forget to make the R,G,B values of each tuple an int, e.g., if R is 255, then 255*0.90 = 229.5, but you need that to be an int value like 191 --- just use int(R*0.90). If you cannot tell much difference, then try darkening by 25% instead..
Brighten. Brighten the image by increasing the values of each of the three RGB channels of the pixel by 10% of its original value. Note, this method should exactly undo the results of performing the Darken filter (as long as none of the image's colors are already as dark as possible), so that doing one operation then the other should result in no net change in the image. Be careful not to produce a color value outside the range of possible values from 0 .. 255. If you cannot tell much difference, then instead try 25%.
GreyScale. Create an image that has only shades of grey values by computing the average value of the pixel's three RGB channels and using that average value for all three channels of the new color. For example, if the pixel has the values (255, 0, 128) for its red, green, and blue channels, respectively; then the resulting color should have the values (127, 127, 127).
Posterize. Create a posterized version of the image by reducing its total number of colors. To do this, you should restrict the values each of the three RGB channels of the pixel so that it takes on four distinct values based on a level-range. Specifically, if the value of each R,G,B is between 0 and 63 inclusive, it should be set to 50; if the value is between 64 and 127 inclusive, it should be set to 100; if the value is between 128 and 191 inclusive, it should be set to 150; and if the value is between 192 and 255 inclusive, it should be set to 200. In this way, the 256 possible values each channel can have is resticted to just 4.
Solarize. Create a solarized version of the image by inverting the values of each of the three RGB channels only if they are too dark, i.e., less that 128. To do this, you should check the value of each channel and only if it is less than 128, invert its value (i.e, subtract it from 255). For example, if the pixel has the values (255, 0, 128) for its red, green, and blue channels, respectively; then the resulting color should have the values (255, 255, 128).

Test these filters by experimenting with them singly and in combinations in the Python module FilterEffects.

Copy and paste your code to these functions in the online form.

Denoise

This image has been shot with a broken camera. The results of the technical inspection concluded that the camera light sensor gave random values for the blue and green channel, while it was diminishing the value of red channel by a factor of roughly 10 times. We would like to "denoise" the picture in such a way it is interpretable by humans by removing the "bad" color channels (blue and green) and enhancing the valid one (red).

  1. Since the blue and green channels have random values, a first step in our denoise process will be to remove the blue and green channels in every pixel of the image. Write the function denoise to return an (R,G,B) tuple in which the R value is unchanged, and the G, and B values are set to zero. Apply this filter to the image noise.png, what does it look like?

  2. Do not worry we still have the red channel to reconstruct our image. Modify denoise so that the red value is multiplied by 10 (and the G, and B values are zero). Run this filter on the images noise.png and iron-puzzle.png. What are the resulting images and from what city do they come from?

  3. Put your code for denoise on the online form.

  4. A second distorted image copper-puzzle.png is provided in your snarf files that is noisy in a different way. Look at it. In this image, the true image is in the blue and green values, however all the blue and green values have all be divided by a number between 10 and 30, so the values are very small. The red values are all just random numbers, noise added on top to obscure things. Write denoise2 to undo these distortions to reveal the true image.

    What is the resulting image? What value did you multiply the G, and B values by to get the "best" image?

  5. Put your code for denoise2 in the online form.

  6. A third image with a hidden message is the image clue2.bmp (check clue.bmp too). Look at both of these images that have hidden messages. To find the hidden message you should change every completely red pixel, e.g., (255,0,0) to black which is all zeros. You should also change any white image (all 255 values) to black as well. Write denoise3 to show these changes. When you do this you'll find a hidden message. What is the hidden message for both clue.bmp and clue2.bmp?

  7. Put your code for denoise3 in the online form

Part 3: Poker Odds

In this part of the lab, we'll be estimating the odds of various hands of poker, specifically a version called 5 card stud, using a Monte Carlo method. The idea is to generate many, many random poker hands, and count which fraction of them are two pairs, full houses, straight flushes, which fraction are four of a kind, etc. See poker hands for types of hands, and Wikipedia/Poker Odds page for probabilities/odds.

For example, here is a full house, 3 of one kind and two of another kind: three jacks and two fours.

The program to calculate odds is started in CardTester.py

Put your answers in the online form.

  1. Most of the code provided is for dealing cards, managing hands, and printing the hands. You should look carefully at both get_rank_counts, is_pair, and simulate to see how the provided code determines how many hands contain one pair. Run the program a few times and estimate what percentage of five-card poker hands contain one pair. Put that answer in the online form.

  2. Write a function is_two_pair and implement it so that it returns true if a hand contains exactly two pairs. What's the body of the function and the probability/odds for two pairs? You'll need to modify simulate too.
    What is the probability of two pairs?

  3. Cut and paste your code for is_two_pair.

  4. Write a function is_threekind to determine when a hand has three of a kind exactly (not four of a kind and not a full house which is three of one rank and two of another rank). For example, [J,J,J,Q,3] is three of a kind, but [3,3,3,8,8] is not because it's a full house.
    What is the probabilty for three of a kind?

  5. Cut and paste your code for is_threekind

  6. Write a function is_fullhouse. What is the probability for is_fullhouse?

  7. Cut and paste your code for is_fullhouse

  8. Challenge: In poker a flush is all cards of the same suit, e.g., all spades, all hearts, etc. Write code to determine if a poker hand is a flush, simulate to find out how many hands are flushes. This might be an overestimate because a straight flush is better than a flush, but that's an extra challenge.

    If you did this then cut and paste your code for flush.

Submit

When you are finished, be sure to submit the google form.