numpy¶https przez http w url obrazu.
Cel: reprezentacja obrazów jako tablice numpy i prosta manipulacja obrazami (jednocześnie jako tutorial operacji tablicowych numpy oraz prostych "niskopoziomowych" technik obróbki grafiki).
import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline
Obrazki monochromatyczne, "ręcznie": tablice numpy $h \times w$ (wysokość na szerokość) z informacją o jasności piksela:
image = np.array([[1, 0.5, 1],
[0.5, 1, 0]])
plt.imshow(image)
plt.show()
plt.imshow(image, cmap="gray", vmin=0, vmax=1)
plt.show()
image = np.random.random(size=(100, 100))
plt.imshow(image, cmap="gray", vmin=0, vmax=1)
plt.show()
np.uint8 - unsigned 8-bit integer, liczba 8-bitowa bez znaku ($2^8 = 256$ możliwości, przy braku znaku daje to zakres wartości $0$-$255$).
image = np.array([[255, 128, 255],
[128, 255, 0]], dtype=np.uint8)
plt.imshow(image)
plt.show()
image = np.array([[255, 128, 255],
[128, 255, 255]], dtype=np.uint8)
plt.imshow(image, vmin=0, vmax=255)
plt.show()
Obrazy kolorowe: tablica $h \times w \times 3$ dla kanałów red, green, blue:
r = np.array([[255, 128, 255],
[128, 255, 255]], dtype=np.uint8)
g = np.array([[0, 64, 80],
[0, 0, 255]], dtype=np.uint8)
b = np.array([[0, 255, 64],
[0, 255, 128]], dtype=np.uint8)
fig, axes = plt.subplots(1, 3, figsize=(15, 5))
axes[0].set_title("red")
axes[0].imshow(r, vmin=0, vmax=255, cmap="gray")
axes[1].set_title("green")
axes[1].imshow(g, vmin=0, vmax=255, cmap="gray")
axes[2].set_title("blue")
axes[2].imshow(b, vmin=0, vmax=255, cmap="gray")
plt.show()
image = np.stack((r,g,b), axis=2) # ułożenie w stos względem osi 2 ("głębokości")
image.shape
(2, 3, 3)
plt.imshow(image)
plt.show()
image = np.random.randint(0, 255, size=(100, 100, 3))
plt.imshow(image)
plt.show()
Automatyczna normalizacja kolorów:
image = np.random.randint(128, 255, size=(100, 100, 3))
plt.imshow(image)
plt.show()
Podobnie dla floatów:
image = np.random.uniform(0, 1, size=(100, 100, 3))
plt.imshow(image)
plt.show()
image = np.random.uniform(0.5, 1, size=(100, 100, 3))
plt.imshow(image)
plt.show()
Wczytywanie (i zapisywanie obrazów): szereg "standardowych" bibliotek, np. imageio, pillow.
pip install imageio
import imageio
mode="L" dla trybu monochromatycznego:
image = imageio.v2.imread("https://math.uni.wroc.pl/~jagiella/files/p1python/cats.jpg", mode="L")
type(image)
numpy.ndarray
image.shape
(361, 557)
image.dtype
dtype('uint8')
image
array([[224, 223, 221, ..., 212, 215, 216],
[222, 228, 225, ..., 217, 209, 208],
[226, 226, 220, ..., 214, 215, 212],
...,
[161, 169, 171, ..., 172, 167, 162],
[170, 165, 167, ..., 139, 167, 159],
[171, 169, 167, ..., 161, 168, 167]], dtype=uint8)
plt.imshow(image, vmin=0, vmax=255, cmap="gray")
plt.show()
W kolorach:
image = imageio.v2.imread("https://math.uni.wroc.pl/~jagiella/files/p1python/cats.jpg")
image.shape
(361, 557, 3)
image.dtype
dtype('uint8')
plt.imshow(image)
plt.show()
Manipulacja obrazami "na surowo" w numpy:
Pojedyncza składowe:
r = image[:, :, 0]
g = image[:, :, 1]
b = image[:, :, 2]
fig, axes = plt.subplots(1, 3, figsize=(15, 5))
axes[0].set_title("red")
axes[0].imshow(r, vmin=0, vmax=255, cmap="gray")
axes[1].set_title("green")
axes[1].imshow(g, vmin=0, vmax=255, cmap="gray")
axes[2].set_title("blue")
axes[2].imshow(b, vmin=0, vmax=255, cmap="gray")
plt.show()
red_only = image.copy()
red_only[:,:,1:] = 0
red_only
array([[[238, 0, 0],
[237, 0, 0],
[234, 0, 0],
...,
[225, 0, 0],
[228, 0, 0],
[229, 0, 0]],
[[236, 0, 0],
[242, 0, 0],
[238, 0, 0],
...,
[230, 0, 0],
[222, 0, 0],
[221, 0, 0]],
[[240, 0, 0],
[239, 0, 0],
[233, 0, 0],
...,
[227, 0, 0],
[228, 0, 0],
[225, 0, 0]],
...,
[[186, 0, 0],
[194, 0, 0],
[196, 0, 0],
...,
[197, 0, 0],
[192, 0, 0],
[189, 0, 0]],
[[194, 0, 0],
[189, 0, 0],
[192, 0, 0],
...,
[167, 0, 0],
[195, 0, 0],
[187, 0, 0]],
[[196, 0, 0],
[194, 0, 0],
[192, 0, 0],
...,
[186, 0, 0],
[193, 0, 0],
[192, 0, 0]]], dtype=uint8)
plt.imshow(red_only)
plt.show()
green_only = image.copy()
green_only[:,:,[0, 2]] = 0
plt.imshow(green_only)
plt.show()
blue_only = image.copy()
blue_only[:,:,:2] = 0
plt.imshow(blue_only)
plt.show()
cat_head = image[40:150, 70:180, :]
plt.imshow(cat_head)
plt.show()
cat_head[:, :, 0] = 0
plt.imshow(cat_head)
plt.show()
plt.imshow(image)
plt.show()
image = imageio.v2.imread("https://math.uni.wroc.pl/~jagiella/files/p1python/cats.jpg")
rcat = image[100:350, 300:480, :]
plt.imshow(rcat)
plt.show()
image[100:350, 100:280] = rcat
plt.imshow(image)
plt.show()
image = imageio.v2.imread("https://math.uni.wroc.pl/~jagiella/files/p1python/cats.jpg")
image[100:350, 100:280, 0] = rcat[:, :, 1]
plt.imshow(image)
plt.show()
image = imageio.v2.imread("https://math.uni.wroc.pl/~jagiella/files/p1python/cats.jpg")
image[100:350, 280:100:-1] = rcat
plt.imshow(image)
plt.show()
Permutacja składowych:
np.array([0, 10, 20, 30, 40, 50])[[2, 3, 1]] # przykład indeksowania ciągiem indeksów
array([20, 30, 10])
image = imageio.v2.imread("https://math.uni.wroc.pl/~jagiella/files/p1python/cats.jpg")
image = image[:, :, [2, 1, 0]]
plt.imshow(image)
plt.show()
image = imageio.v2.imread("https://math.uni.wroc.pl/~jagiella/files/p1python/cats.jpg")
image = 255 - image
plt.imshow(image)
plt.show()
image = imageio.v2.imread("https://math.uni.wroc.pl/~jagiella/files/p1python/cats.jpg")
image = image / 255
plt.imshow(image)
plt.show()
"Naiwna" zmiana jasności:
plt.imshow(image / 2)
plt.show()
plt.imshow(0.5 + image / 2)
plt.show()
Korekta gamma:
Dla $\gamma > 0$ zmieniamy natężenie piksela (lub natężenie kanału piksela) zgodnie z przekształceniem $x \mapsto x^\gamma$.
image = imageio.v2.imread("https://math.uni.wroc.pl/~jagiella/files/p1python/cats.jpg")
image = image / 255
fig, axes = plt.subplots(2, 2)
for ax, gamma in zip(axes.ravel(), [0.5, 1, 1.5, 2]):
ax.set_title(f"$\gamma = {gamma}$")
ax.imshow(image ** gamma)
plt.tight_layout()
image = imageio.v2.imread("https://math.uni.wroc.pl/~jagiella/files/p1python/cats.jpg", mode="L") / 255 # monochromatyczny
dark_parts = image < 0.5
dark_parts
array([[False, False, False, ..., False, False, False],
[False, False, False, ..., False, False, False],
[False, False, False, ..., False, False, False],
...,
[False, False, False, ..., False, False, False],
[False, False, False, ..., False, False, False],
[False, False, False, ..., False, False, False]])
plt.imshow(dark_parts)
plt.show()
image[dark_parts] = 0
plt.imshow(image, cmap="gray", vmin=0, vmax=1)
plt.show()
light_parts = image > 0.8
image[light_parts] = 1
plt.imshow(image, cmap="gray", vmin=0, vmax=1)
plt.show()
image = imageio.v2.imread("https://math.uni.wroc.pl/~jagiella/files/p1python/cats.jpg") / 255
image[image < 0.5] = 0
plt.imshow(image)
plt.show()