129 lines
4.5 KiB
Python
Executable File
129 lines
4.5 KiB
Python
Executable File
"""CSC110 Fall 2021 Assignment 1, Part 4
|
|
|
|
Instructions (READ THIS FIRST!)
|
|
===============================
|
|
|
|
Please follow the instructions in the assignment handout to complete this file.
|
|
|
|
Copyright and Usage Information
|
|
===============================
|
|
|
|
This file is provided solely for the personal and private use of students
|
|
taking CSC110 at the University of Toronto St. George campus. All forms of
|
|
distribution of this code, whether as given or with any changes, are
|
|
expressly prohibited. For more information on copyright for CSC110 materials,
|
|
please consult our Course Syllabus.
|
|
|
|
This file is Copyright (c) 2021 Mario Badr and Tom Fairgrieve.
|
|
"""
|
|
import random
|
|
|
|
import a1_image
|
|
|
|
|
|
def maximize_channels(old_pixel: tuple, value: int) -> tuple:
|
|
"""Return a new pixel that has colour channels set to the larger of value or the corresponding
|
|
colour channel in old_pixel.
|
|
|
|
* Assumed that value is positive
|
|
|
|
>>> example_pixel = (100, 12, 155)
|
|
>>> maximize_channels(example_pixel, 128)
|
|
(128, 128, 155)
|
|
"""
|
|
return tuple([max(chan, value) for chan in old_pixel])
|
|
|
|
|
|
def divide_channels(old_pixel: tuple, denominator: int) -> tuple:
|
|
"""Return a new pixel that has colour channels set to the quotient from dividing the
|
|
corresponding colour channel in old_pixel by denominator.
|
|
|
|
* Assumed that denominators are positive integers.
|
|
|
|
>>> example_pixel = (100, 12, 155)
|
|
>>> divide_channels(example_pixel, 2)
|
|
(50, 6, 77)
|
|
"""
|
|
return tuple([chan // denominator for chan in old_pixel])
|
|
|
|
|
|
def add_pepper(pixel_data: list, k: int) -> list:
|
|
"""Return a new list of pixels formed from the corresponding pixels in pixel_data that has some
|
|
randomly chosen black pixels.
|
|
|
|
The chance that a new pixel will be black is based on k. The probability that a pixel is
|
|
black is to be : 1 / (k + 1)
|
|
|
|
Assume that k >= 0.
|
|
|
|
You must use the divide_channels function (above).
|
|
|
|
Hint: use the function random.choice to choose from a list of denominators. What denominator,
|
|
passed to divide_channels, causes a pixel to not change its colour? What denominator causes a
|
|
pixel to become black?
|
|
|
|
Because of the randomness, we can't specify an exact doctest.
|
|
"""
|
|
return [divide_channels(pixel, random.choice([1] * k + [256])) for pixel in pixel_data]
|
|
|
|
|
|
def add_salt(pixel_data: list, k: int) -> list:
|
|
"""Return a new list of pixels formed from the corresponding pixels in pixel_data that has some
|
|
randomly chosen white pixels.
|
|
|
|
The chance that a new pixel will be white is based on k. The probability that a pixel is
|
|
white is to be : 1 / (k + 1)
|
|
|
|
Assume that k >= 0.
|
|
|
|
You must use the maximize_channels function (above).
|
|
|
|
Hint: use the function random.choice to choose from a list of values. What value, passed to
|
|
maximize_channels, causes a pixel to not change its colour? What value causes a pixel to become
|
|
white?
|
|
|
|
Because of the randomness, we can't specify an exact doctest.
|
|
"""
|
|
return [maximize_channels(pixel, random.choice([0] * k + [255])) for pixel in pixel_data]
|
|
|
|
|
|
def add_salt_and_pepper(pixel_data: list, k: int) -> list:
|
|
"""Return a new list of pixels formed from the corresponding pixels in pixel_data
|
|
that has some randomly chosen white pixels and some randomly chosen black pixels.
|
|
|
|
You must use the add_pepper then add_salt functions, in that order, with both using noise
|
|
probabilities determined by k.
|
|
|
|
Because of the randomness, we can't specify an exact doctest.
|
|
"""
|
|
pixel_data = add_pepper(pixel_data, k)
|
|
pixel_data = add_salt(pixel_data, k)
|
|
return pixel_data
|
|
|
|
|
|
def run_salt_and_pepper_example(source: str, destination: str, k: int) -> None:
|
|
"""Add salt and pepper noise to an example image file at source and save the result in
|
|
destination, where noisiness is a function of k.
|
|
|
|
You can run this function with an image of your choice. Make sure the image is not too large or
|
|
this will take a long time.
|
|
"""
|
|
original_pixel_data, width, height = a1_image.load_image(source)
|
|
noisy_pixel_data = add_salt_and_pepper(original_pixel_data, k)
|
|
a1_image.save_image(destination, noisy_pixel_data, width, height)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
import doctest
|
|
doctest.testmod()
|
|
|
|
run_salt_and_pepper_example('images/horses.png', 'images/noisy-horses.png', 16)
|
|
|
|
# When you are ready to check your work with python_ta, uncomment the following lines.
|
|
# (Delete the "#" and space before each line.)
|
|
import python_ta
|
|
python_ta.check_all(config={
|
|
'extra-imports': ['random', 'a1_image'],
|
|
'max-line-length': 100
|
|
})
|