93 lines
3.7 KiB
Python
93 lines
3.7 KiB
Python
import UZ_utils as uz
|
||
import numpy as np
|
||
import numpy.typing as npt
|
||
|
||
#######################################
|
||
# EXCERCISE 1: Basic image processing #
|
||
#######################################
|
||
|
||
def excercise_one() -> None:
|
||
image = one_a()
|
||
one_b(image)
|
||
one_c(image)
|
||
one_d(60, 180, 180, 340, image)
|
||
|
||
def one_a() -> npt.NDArray[np.float64]:
|
||
"""
|
||
Read the image from the file umbrellas.jpg and display it
|
||
"""
|
||
image = uz.imread('./images/umbrellas.jpg')
|
||
uz.imshow(image, 'Birdie')
|
||
return image
|
||
|
||
def one_b(image: npt.NDArray[np.float64]) -> None:
|
||
"""
|
||
Convert the loaded image to grayscale. A very simple way of doing this is summing
|
||
up the color channels and dividing the result by 3, effectively averaging the values.
|
||
The issue, however, is that the sum easily reaches beyond the np.uint8 range. We
|
||
can avoid that by casting the data to a floating point type. You can access a specific
|
||
image channel using the indexing syntax like red = I[:,:,0].
|
||
"""
|
||
grayscale_image = np.zeros(image.shape[:2])
|
||
|
||
for i in range(image.shape[0]):
|
||
for j in range(image.shape[1]):
|
||
grayscale_image[i, j] = (image[i, j, 0] + image[i,j, 1] + image[i, j, 2]) / 3
|
||
|
||
uz.imshow(grayscale_image, 'Umbrellas grayscale')
|
||
|
||
def one_c(image: npt.NDArray[np.float64]) -> None:
|
||
"""
|
||
Cut and display a specific part of the loaded image. Extract only one of the channels
|
||
so you get a grayscale image. You can do this by indexing along the first two axes,
|
||
for instance: cutout=I[130:260, 240:450, 1]. You can display multiple images in
|
||
a single window using plt.subplot().
|
||
Grayscale images can be displayed using different mappings (on a RGB monitor,
|
||
every value needs to be mapped to a RGB triplet). Pyplot defaults to a color map
|
||
named viridis, but often it is preferable to use a grayscale color map. This can be set
|
||
with an additional argument to plt.imshow, like plt.imshow(I, cmap=’gray’).
|
||
Question: Why would you use different color maps?
|
||
Answer:
|
||
"""
|
||
print(image.shape)
|
||
uz.imshow(image[50:200, 100:400, 2])
|
||
|
||
def one_d(startx: int, endx: int, starty: int, endy: int, image:npt.NDArray[np.float64]) -> None:
|
||
"""
|
||
You can also replace only a part of the image using indexing. Write a script that
|
||
inverts a rectangular part of the image. This can be done pixel by pixel in a loop or
|
||
by using indexing.
|
||
Question: How is inverting a grayscale value defined for uint8 ?
|
||
Answer:
|
||
"""
|
||
inverted_image = image.copy()
|
||
|
||
for i in range(startx, endx):
|
||
for j in range(starty, endy):
|
||
inverted_image[i, j, 0] = 1 - image[i, j, 0]
|
||
inverted_image[i, j, 1] = 1 - image[i, j, 1]
|
||
inverted_image[i, j, 2] = 1 - image[i, j, 2]
|
||
|
||
uz.imshow(image, 'Shid')
|
||
|
||
def one_e() -> None:
|
||
"""
|
||
Perform a reduction of grayscale levels in the image. First read the image from
|
||
umbrellas.jpg and convert it to grayscale. You can write your own function for
|
||
grayscale conversion or use the function in UZ_utils.py.
|
||
Convert the grayscale image to floating point type. Then, rescale the image values
|
||
so that the largest possible value is 63. Convert the image back to uint8 and display
|
||
both the original and the modified image. Notice that both look the same. Pyplot
|
||
tries to maximize the contrast in displayed images by checking their values and
|
||
scaling them to cover the entire uint8 interval. If you want to avoid this, you need
|
||
to set the maximum expected value when using plt.imshow(), like plt.imshow(I,
|
||
vmax=255. Use this to display the resulting image so the change is visible.
|
||
"""
|
||
print("todo")
|
||
|
||
def main() -> None:
|
||
excercise_one()
|
||
|
||
if __name__ == "__main__":
|
||
main()
|