Excercis one refactored
parent
f35deb07fb
commit
cc771141a2
|
@ -1,9 +1,10 @@
|
|||
import UZ_utils as uz
|
||||
import numpy as np
|
||||
import numpy.typing as npt
|
||||
from matplotlib import pyplot as plt
|
||||
import random
|
||||
import cv2
|
||||
import uz_framework.image as uz_image
|
||||
import UZ_utils as uz
|
||||
|
||||
#######################################
|
||||
# EXCERCISE 1: Basic image processing #
|
||||
|
@ -11,18 +12,22 @@ import cv2
|
|||
|
||||
def excercise_one() -> None:
|
||||
image = one_a()
|
||||
# one_b(image)
|
||||
# one_c(image)
|
||||
one_d(100, 200, 200, 400, image)
|
||||
# one_e()
|
||||
#one_b(image)
|
||||
#one_c(image)
|
||||
#one_d(100, 200, 200, 400, image)
|
||||
one_e()
|
||||
|
||||
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.ImageType.float64)
|
||||
uz.imshow(image, 'Umbrellas')
|
||||
return image
|
||||
umbrellas = uz_image.imread('./images/umbrellas.jpg', uz_image.ImageType.float64)
|
||||
|
||||
plt.imshow(umbrellas)
|
||||
plt.suptitle("Umbrellas Picture")
|
||||
plt.show()
|
||||
|
||||
return umbrellas
|
||||
|
||||
def one_b(image: npt.NDArray[np.float64]) -> None:
|
||||
"""
|
||||
|
@ -32,13 +37,12 @@ def one_b(image: npt.NDArray[np.float64]) -> None:
|
|||
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
|
||||
grayscale_image = uz_image.transform_coloured_image_to_grayscale(image)
|
||||
|
||||
plt.imshow(grayscale_image, cmap='gray')
|
||||
plt.suptitle("Umbrellas Grayscale")
|
||||
plt.show()
|
||||
|
||||
uz.imshow(grayscale_image, 'Umbrellas grayscale')
|
||||
|
||||
def one_c(image: npt.NDArray[np.float64]) -> None:
|
||||
"""
|
||||
|
@ -53,10 +57,30 @@ def one_c(image: npt.NDArray[np.float64]) -> None:
|
|||
Question: Why would you use different color maps?
|
||||
Answer:
|
||||
"""
|
||||
uz.imshow(image[50:200, 100:400, 2], "Just one piece of umbrellas")
|
||||
cutout_0 = image[50:200, 100:400, 0]
|
||||
cutout_1 = image[50:200, 100:400, 1]
|
||||
cutout_2 = image[50:200, 100:400, 2]
|
||||
|
||||
fig, axs = plt.subplots(1, 3)
|
||||
fig.suptitle('Displaying cutouts for different image channels')
|
||||
|
||||
axs[0].imshow(cutout_0, cmap='gray')
|
||||
axs[0].set(title='Channel 0')
|
||||
|
||||
axs[1].imshow(cutout_1, cmap='gray')
|
||||
axs[1].set(title='Channel 1')
|
||||
|
||||
axs[2].imshow(cutout_2, cmap='gray')
|
||||
axs[2].set(title='Channel 2')
|
||||
|
||||
plt.show
|
||||
|
||||
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.
|
||||
|
||||
(height, width, color)
|
||||
(x , y , color)
|
||||
y ->
|
||||
|
@ -67,29 +91,18 @@ def one_d(startx: int, endx: int, starty: int, endy: int, image:npt.NDArray[np.f
|
|||
# #
|
||||
# #
|
||||
#################
|
||||
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]
|
||||
|
||||
fig, (ax0, ax1) = plt.subplots(1, 2)
|
||||
inverted_image = uz_image.invert_coloured_image_part(image, startx, endx, starty, endy)
|
||||
fig, axs = plt.subplots(1, 2)
|
||||
fig.suptitle("Lomberlini")
|
||||
|
||||
|
||||
ax0.imshow(image, cmap="gray")
|
||||
ax1.imshow(inverted_image, vmax=255, cmap="gray")
|
||||
|
||||
ax0.set(title="Original image")
|
||||
ax1.set(title="Inverted image")
|
||||
axs[0].imshow(image)
|
||||
axs[0].set(title="Original Image")
|
||||
axs[1].imshow(inverted_image, vmax=255)
|
||||
axs[1].set(title="Inverted part of Image")
|
||||
|
||||
plt.show()
|
||||
|
||||
|
@ -106,18 +119,17 @@ def one_e() -> None:
|
|||
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.
|
||||
"""
|
||||
grayscale_image = uz.imread_gray("./images/umbrellas.jpg", uz.ImageType.float64)
|
||||
grayscale_image = uz_image.imread_gray("./images/umbrellas.jpg", uz_image.ImageType.float64)
|
||||
upscaled_grayscale_image = (grayscale_image.copy() * 63).astype(np.uint8)
|
||||
|
||||
fig, (ax0, ax1) = plt.subplots(1, 2)
|
||||
fig, axs = plt.subplots(1, 2)
|
||||
fig.suptitle("Lomberlini")
|
||||
|
||||
|
||||
ax0.imshow(grayscale_image, cmap="gray")
|
||||
ax1.imshow(upscaled_grayscale_image, vmax=255, cmap="gray")
|
||||
|
||||
ax0.set(title="Original grayscale image")
|
||||
ax1.set(title="Upscaled grayscale image")
|
||||
axs[0].imshow(grayscale_image, cmap="gray")
|
||||
axs[0].set(title="Original grayscale image")
|
||||
axs[1].imshow(upscaled_grayscale_image, vmax=255, cmap="gray")
|
||||
axs[1].set(title="Upscaled grayscale image")
|
||||
|
||||
plt.show()
|
||||
|
||||
|
@ -582,9 +594,9 @@ def three_e():
|
|||
|
||||
|
||||
def main() -> None:
|
||||
#excercise_one()
|
||||
excercise_one()
|
||||
#excercise_two()
|
||||
excercise_three()
|
||||
#excercise_three()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
|
||||
import numpy as np
|
||||
import cv2 as cv2
|
||||
from matplotlib import pyplot as plt
|
||||
from PIL import Image
|
||||
from typing import Union
|
||||
import numpy.typing as npt
|
||||
import enum
|
||||
|
||||
class ImageType(enum.Enum):
|
||||
uint8 = 0
|
||||
float64 = 1
|
||||
|
||||
def imread(path: str, type: ImageType) -> npt.NDArray[np.float64] or npt.NDArray[np.uint8]:
|
||||
"""
|
||||
Reads an image in RGB order. Image type is transformed from uint8 to float, and
|
||||
range of values is reduced from [0, 255] to [0, 1].
|
||||
"""
|
||||
I = Image.open(path).convert('RGB') # PIL image.
|
||||
I = np.asarray(I) # Converting to Numpy array.
|
||||
if type == ImageType.float64:
|
||||
I = I.astype(np.float64) / 255
|
||||
return I
|
||||
elif type == ImageType.uint8:
|
||||
return I
|
||||
|
||||
raise Exception("Wrong image format picked!")
|
||||
|
||||
|
||||
def imread_gray(path: str, type: ImageType) -> npt.NDArray[np.float64] or npt.NDArray[np.uint8]:
|
||||
"""
|
||||
Reads an image in gray. Image type is transformed from uint8 to float, and
|
||||
range of values is reduced from [0, 255] to [0, 1].
|
||||
"""
|
||||
|
||||
I = Image.open(path).convert('L') # PIL image opening and converting to gray.
|
||||
I = np.asarray(I) # Converting to Numpy array.
|
||||
|
||||
if type == ImageType.float64:
|
||||
I = I.astype(np.float64) / 255
|
||||
return I
|
||||
elif type == ImageType.uint8:
|
||||
return I
|
||||
|
||||
raise Exception("Wrong image format picked!")
|
||||
|
||||
def signal_show(*signals):
|
||||
"""
|
||||
Plots all given 1D signals in the same plot.
|
||||
Signals can be Python lists or 1D numpy array.
|
||||
"""
|
||||
for s in signals:
|
||||
if type(s) == np.ndarray:
|
||||
s = s.squeeze()
|
||||
plt.plot(s)
|
||||
plt.show()
|
||||
|
||||
|
||||
def convolve(I: np.ndarray, *ks):
|
||||
"""
|
||||
Convolves input image I with all given kernels.
|
||||
|
||||
:param I: Image, should be of type float64 and scaled from 0 to 1.
|
||||
:param ks: 2D Kernels
|
||||
:return: Image convolved with all kernels.
|
||||
"""
|
||||
for k in ks:
|
||||
k = np.flip(k) # filter2D performs correlation, so flipping is necessary
|
||||
I = cv2.filter2D(I, cv2.CV_64F, k)
|
||||
return I
|
||||
|
||||
def transform_coloured_image_to_grayscale(image: npt.NDArray[np.float64]) -> npt.NDArray[np.float64]:
|
||||
"""
|
||||
Accepts float64 picture with three colour channels and returns float64 grayscale image
|
||||
with one channel.
|
||||
"""
|
||||
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
|
||||
|
||||
print(grayscale_image)
|
||||
print(grayscale_image.shape)
|
||||
|
||||
return grayscale_image
|
||||
|
||||
def invert_coloured_image_part(image: npt.NDArray[np.float64] or npt.NDArray[np.uint8], startx: int, endx: int, starty: int, endy: int) -> npt.NDArray[np.float64] or npt.NDArray[np.uint8]:
|
||||
inverted_image = image.copy()
|
||||
|
||||
if image.dtype.type == np.float64:
|
||||
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]
|
||||
print('wtf')
|
||||
return inverted_image
|
||||
elif image.dtype.type == np.uint8:
|
||||
for i in range(startx, endx):
|
||||
for j in range(starty, endy):
|
||||
inverted_image[i, j, 0] = 255 - image[i, j, 0]
|
||||
inverted_image[i, j, 1] = 255 - image[i, j, 1]
|
||||
inverted_image[i, j, 2] = 255 - image[i, j, 2]
|
||||
return inverted_image
|
||||
|
||||
raise Exception("Unrecognized image format!")
|
||||
|
||||
def invert_coloured_image(image: npt.NDArray[np.float64] or npt.NDArray[np.uint8]) -> npt.NDArray[np.float64] or npt.NDArray[np.uint8]:
|
||||
return invert_coloured_image_part(image, 0, image.shape[0], 0, image.shape[1])
|
||||
|
||||
|
||||
def convert_float64_array_to_uint8_array(a: npt.NDArray[np.float64]) -> npt.NDArray[np.uint8]:
|
||||
return a.astype(np.uint8)
|
Loading…
Reference in New Issue