from simpleimage import SimpleImage
We've seen in class how we can use filters to transform real and interesting images. In this exercise we are going to write more of our own fun filters.
To start, let's load up a simple image from class
einstein = SimpleImage("images/einstein.jpeg")
einstein.show()
Let's invert the colors on this image, which will make dark pixels light and light pixels dark. Here we will be inverting each color individually, so pixels which were very red will become very not red, and so on. This means that visually the image may not actually get darker or brighter as a whole.
To invert one color for one pixel, do this:
pixel = image.get_rgb(x, y)
old_red = pixel[0] # This is the current value for red in this pixel
new_red = 255 - old_red # Inverting means subtracting from the maximum value
image.set_rgb(x, y, new_red, new_green, new_blue)
# Work out how to get new_green and new_blue yourself!
def invert_colors(image):
new_image = SimpleImage.blank(image.width, image.height)
for x in range(new_image.width):
for y in range(new_image.height):
pixel = image.get_rgb(x, y)
old_red = pixel[0]
old_green = pixel[1]
old_blue = pixel[2]
# Your code here. It should look similar to the example below.
# new_red = ???
# new_green = ???
# new_blue = ???
new_image.set_rgb(x, y, new_red, new_green, new_blue)
return new_image
invert_colors(einstein).show()
# For reference, here's the red_gradient_filter from the lecture
def red_gradient_filter(image):
new_image = SimpleImage.blank(image.width, image.height)
for x in range(new_image.width):
for y in range(new_image.height):
pixel = image.get_rgb(x, y)
red = min(255, pixel[0] + x)
green = pixel[1]
blue = pixel[2]
new_image.set_rgb(x, y, red, green, blue)
return new_image
--------------------------------------------------------------------------- NameError Traceback (most recent call last) Cell In[3], line 15 13 image.set_rgb(x, y, new_red, new_green, new_blue) 14 return new_image ---> 15 invert_colors(einstein).show() 18 # For reference, here's the red_gradient_filter from the lecture 19 def red_gradient_filter(image): Cell In[3], line 13, in invert_colors(image) 8 old_blue = pixel[2] 9 # Your code here. It should look similar to the example below. 10 # new_red = ??? 11 # new_green = ??? 12 # new_blue = ??? ---> 13 image.set_rgb(x, y, new_red, new_green, new_blue) 14 return new_image NameError: name 'new_red' is not defined
What if we changed the red and green variable names? Will the function do anything different?
Do these two programs do the same thing?
Program 1
red = pixel[0] # This is the current value for red in this pixel
new_red = 255 - red
Program 2
bicycle = pixel[0] # This is the current value for red in this pixel
new_red = 255 - bicycle
# Your answers here (Yes/No, Why?)
#
Next we will turn a color image to greyscale. Here's an example:
Normal | Grayscale |
---|---|
Complete the grayscale()
function below and test it.
The technique to making a pixel grayscale is to make each color channel the average of all three channels, ie
average = (old_red + old_green + old_blue) // 3
new_red = average
new_green = average
new_blue = average
rainbow = SimpleImage("images/rainbow.jpeg")
rainbow.show()
def grayscale(image):
# Your code here
return image
grayscale(rainbow).show()
Can you make only the left side of the image gray scale?
You only need to change one line in your previous filter.
rainbow = SimpleImage("images/rainbow.jpeg")
rainbow.show()
def half_grayscale(image):
# Your code here
return image
half_grayscale(rainbow).show()
Another filter is flip. Vertical flip turns an image upside down; horizontal flip reverses the image left to right. Here's an example:
Normal | Flipped |
---|---|
Complete the flip()
function below and test it.
Hint: For this question, instead of changing one pixel by itself, you will need to swap the values for two pixels that are mirror of each other. Start by swapping the top-left pixel with the top-right pixel. Draw out a small example on paper to see how the pixels change places.
soccerball = SimpleImage("images/soccer_ball.jpeg")
soccerball.show()
# You will likely want to keep the same nested For loop structure. But this time instead of changing the colors, you
# want to swap the color values for two pixels. For a pixel (x,y), which is the mirror pixel it should be swapped with?
def flip_horizontal(image):
# Your code here
return image
flip_horizontal(soccerball).show()
Finally, let's rotate the image. First, we do this counter clockwise. Example:
Normal | Rotated Left |
---|---|
Complete the rotate_left
function below.
You want to create a new image here. You want to copy some pixels from the old image and put them in a different position in the new image. For instance, the top right pixel in the old image will get put in the top left corner in the new image.
square = SimpleImage("images/square.jpeg")
square.show()
# def rotate_left(image):
# width = image.width
# height = image.height
# new_image = SimpleImage.blank(width, height)
# # Your code here
# return new_image
rotate_left(square).show()
Bonus: Now write the rotate_right
function, BUT you can only use four lines of code and no loop! (Hint: now that you have rotate_left
you don't have to write rotate_right
from scratch.
square = SimpleImage("images/square.jpeg")
square.show()
def rotate_right(image):
# Only 4 lines of code here. Actually, you can also do it in one line....
rotate_right(square).show()
(optional) Just for fun, get creative and write a function implementing any filter of your choosing. You can change colors, move pixels, anything you want to do. Show it to one of your TAs once you're done and tell them about what it does.