Konvoluce dvourozměrných signálů
Co se dozvíte v článku
- Konvoluce dvourozměrných signálů
- Jádro konvoluce vyjádřené maticí
- Funkce signal.convolve
- Rozmazání obrázku s využitím konvolučního jádra 3×3 hodnoty
- Gaussovský filtr s konvolučním jádrem 3×3 prvky
- Detekce hran ve vertikálním směru
- Detekce hran v horizontálním směru
- Sofistikovanější konvoluční jádra
- Gaussovský filtr: vliv hodnoty sigma na provedenou operaci
- Laplaceův filtr
- Aplikace Laplaceova filtru na rastrový obrázek
- Kombinace původního obrázku s výsledkem aplikace Laplaceova filtru
- Sobelův operátor
- Sobelův operátor nabízený knihovnou SciPy
- Aplikace Sobelova filtru na rastrový obrázek
- Kombinace původního obrázku a výsledku aplikace Sobelova operátoru
- Otestování filtrů na zašuměném obrázku
- Výsledky aplikace Gaussovského filtru
- Repositář s demonstračními příklady
- Odkazy na Internetu
V pořadí již šestém článku o knihovně SciPy dokončíme popis operací, které je možné provádět s dvourozměrnými signály, tj. především s rastrovými obrázky. Připomeňme si, že minule jsme se zabývali transformacemi rastrových obrázků. Mezi tyto operace patří DFT (realizovaná jako FFT) a dále DCT i DST, tedy diskrétní kosinová a sinová transformace. Dnes si ukážeme zejména klasickou konvoluci s konvolučním jádrem zadaným maticí, ovšem nezapomeneme ani na funkce poskytované balíčkem ndimage, ve kterém se (kromě dalších funkcí) nachází i realizace užitečných filtrů.
Jádro konvoluce vyjádřené maticí
Jádro konvoluce je možné v případě, že se konvoluce aplikuje na rastrové obrázky, vyjádřit maticí. Při použití knihovny SciPy je matice většinou reprezentována n-rozměrným polem (nd-array) podporovaným knihovnou NumPy. Konvolučních filtrů tohoto typu existuje celá řada, od velmi primitivních, až po relativně sofistikované filtry. Jen pro zajímavost se na některá konvoluční jádra podívejme.
Rozmazání obrázku tak, že se každý pixel zprůměruje se sousedními pixely (čtyřokolí). Výsledek se dělí pěti:
[ 0, 1, 0 ] [ 1, 1, 1 ] [ 0, 1, 0 ]
Rozmazání obrázku tak, že se každý pixel zprůměruje se sousedními pixely (osmiokolí). Výsledek se dělí devíti:
[ 1, 1, 1 ] [ 1, 1, 1 ] [ 1, 1, 1 ]
Gaussův filtr, výsledek se dělí šestnácti:
[ 1, 2, 1 ] [ 2, 4, 2 ] [ 1, 2, 1 ]
Jedna z možností realizace filtru pro zvýraznění změn v obraze:
[ 0, -1, 0 ] [-1, 5, -1 ] [ 0, -1, 0 ]
Detekce hran:
[ 0, -1, 0 ] [-1, 4, -1 ] [ 0, -1, 0 ]
Jedna z forem Laplaceova filtru:
[ 0, 1, 0 ] [ 1, -4, 1 ] [ 0, 1, 0 ]
Sobelovy operátory:
[-1, 0, 1] [-2, 0, 2] [-1, 0, 1] [-1, -2, -1] [ 0, 0, 0] [ 1, 2, 1]
Funkce signal.convolve
Velmi často volanou operací, která se při zpracování signálů používá, je konvoluce (convolution). Ta může být provedena jak pro jednorozměrné signály (zvukové filtry atd.), tak i pro vícerozměrné signály (známé jsou konvoluční filtry v oblasti zpracování obrazu, které nás primárně zajímají právě v dnešním článku). Konvoluci dvou signálů, typicky zpracovávaného signálu a konvolučního jádra, lze vypočítat s využitím funkce nazvané přímočaře convolve (nalezneme ji v podbalíčku signal):
Help on function convolve in module scipy.signal._signaltools:
convolve(in1, in2, mode='full', method='auto')
Convolve two N-dimensional arrays.
Convolve `in1` and `in2`, with the output size determined by the
`mode` argument.
Parameters
----------
in1 : array_like
First input.
in2 : array_like
Second input. Should have the same number of dimensions as `in1`.
mode : str {'full', 'valid', 'same'}, optional
A string indicating the size of the output:
``full``
The output is the full discrete linear convolution
of the inputs. (Default)
``valid``
The output consists only of those elements that do not
rely on the zero-padding. In 'valid' mode, either `in1` or `in2`
must be at least as large as the other in every dimension.
``same``
The output is the same size as `in1`, centered
with respect to the 'full' output.
method : str {'auto', 'direct', 'fft'}, optional
A string indicating which method to use to calculate the convolution.
``direct``
The convolution is determined directly from sums, the definition of
convolution.
``fft``
The Fourier Transform is used to perform the convolution by calling
`fftconvolve`.
``auto``
Automatically chooses direct or Fourier method based on an estimate
of which is faster (default). See Notes for more detail.
.. versionadded:: 0.19.0
Returns
-------
convolve : array
An N-dimensional array containing a subset of the discrete linear
convolution of `in1` with `in2`.
Rozmazání obrázku s využitím konvolučního jádra 3×3 hodnoty
Při úpravách fotografií nebo naskenovaných obrázků se poměrně často můžeme setkat s požadavkem na odstranění šumu z obrazu nebo z jeho vybrané části. K tomuto účelu můžeme použít poměrně velké množství více či méně sofistikovaných filtrů, které lze pro odstranění šumu použít. Nejjednodušším a taktéž nejrychlejším filtrem, který dokáže odstranit vysoké frekvence v obrazu a tím i šum (bohužel spolu s ostrými hranami) je filtr, který pracuje velmi jednoduše – spočítá průměrnou hodnotu devíti sousedních pixelů tvořících blok o velikosti 3×3 pixely a tuto hodnotu uloží do pixelu ležícího přesně uprostřed bloku (operace je samozřejmě provedena pro všechny pixely v obrazu). Výsledkem je sice obraz s odstraněným vysokofrekvenčním šumem, ale současně s potlačením šumu došlo k rozmazání všech jednopixelových hran na přechody široké minimálně tři pixely. Z implementačního hlediska se jedná o konvoluční filtr, jehož konvoluční jádro je velmi jednoduché:
1/9 1/9 1/9 1/9 1/9 1/9 1/9 1/9 1/9
Nás ovšem nebudou zajímat absolutní hodnoty výsledky, takže klidně můžeme použít jádro:
1 1 1 1 1 1 1 1 1
Programová aplikace takového konvolučního jádra může vypadat následovně:
import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import convolve
import scipy.datasets as datasets
# načtení matice
ascent = datasets.ascent()
# matice 3x3 prvky obsahující jedničky (NEjedná se o jednotkovou matici)
kernel = np.ones([3, 3])
print("Kernel:")
print(kernel)
# výpočet konvoluce
filtered = convolve(ascent, kernel)
# zobrazení výsledku
plt.imshow(filtered, cmap="gray")
plt.title("2D convolution")
# uložení grafu s průběhem signálu
plt.savefig("convolve_2d_1.png")
# zobrazení grafu
plt.show()
A takto by měl vypadat výsledek:
Obrázek 1: Rozostření obrázku s využitím jednoduchého konvolučního filtru.
Gaussovský filtr s konvolučním jádrem 3×3 prvky
Dalším typem filtru určeného k odstranění šumu z rastrových obrázků je Gaussovský filtr (Gaussian Blur), v němž se též provádí průměrování hodnot sousedních pixelů, ale, na rozdíl od filtru předchozího, jsou těmto pixelům přiřazeny různé váhy v závislosti na jejich vzdálenosti od středního pixelu. Váhy jsou zvoleny tak, aby (velmi nepřesně) aproximovaly Gaussovo rozložení v 2D:
1 2 1 2 4 2 1 2 1
Taktéž v tomto případě se jedná o konvoluční filtr, ovšem velikost konvolučního jádra je možné měnit. Běžně se používají velikosti jádra 3×3 či 5×5 pixelů, protože při větší velikosti jádra již mají vzdálenější pixely tak nízkou váhu, že se výpočet pouze zbytečně prodlužuje bez většího vlivu na výsledný obrázek.
Opět se podívejme na jednoduchou implementaci tohoto filtru (později si ukážeme sofistikovanější řešení):
import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import convolve
import scipy.datasets as datasets
# načtení matice
ascent = datasets.ascent()
kernel = np.array([
[ 1, 2, 1 ],
[ 2, 4, 2 ],
[ 1, 2, 1 ],
])
print("Kernel:")
print(kernel)
# výpočet konvoluce
filtered = convolve(ascent, kernel)
# zobrazení výsledku
plt.imshow(filtered, cmap="gray")
plt.title("2D convolution")
# uložení grafu s průběhem signálu
plt.savefig("convolve_2d_2.png")
# zobrazení grafu
plt.show()
Nyní bude výsledek vypadat takto:
Obrázek 2: Rozostření obrázku s využitím jednoduchého Gaussovského konvolučního filtru.
Detekce hran ve vertikálním směru
Mezi další typy jednoduchých konvolučních filtrů patří filtry určené pro detekci hran v horizontálním či vertikálním směru (hledání hran v jiných směrech již vyžaduje sofistikovanější operace). Teoreticky lze konvoluční jádra těchto filtrů reprezentovat sloupcovým či řádkovým vektorem, nikoli maticí, ovšem pro porovnání s dalšími příklady budu stále používat matice 3×3 prvky. Detekce hran ve vertikálním směru tím nejjednodušším možným filtrem může vypadat například takto:
import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import convolve
import scipy.datasets as datasets
# načtení matice
ascent = datasets.ascent()
kernel = np.array([
[-1, -1, -1],
[ 0, 0, 0],
[ 1, 1, 1],
])
print("Kernel:")
print(kernel)
# výpočet konvoluce
filtered = convolve(ascent, kernel)
# zobrazení výsledku
plt.imshow(filtered, cmap="gray")
plt.title("2D convolution")
# uložení grafu s průběhem signálu
plt.savefig("convolve_2d_3.png")
# zobrazení grafu
plt.show()
Výsledek provedené konvoluce:
Obrázek 3: Hledání hran v obrázku s využitím konvolučního filtru.
Detekce hran v horizontálním směru
Pouhou transpozicí matice použité v předchozím příkladu lze realizovat hledání hran ve směru horizontálním. Podívejme se na upravený příklad, který tuto operaci provádí:
import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import convolve
import scipy.datasets as datasets
# načtení matice
ascent = datasets.ascent()
kernel = np.array([
[-1, 0, 1],
[-1, 0, 1],
[-1, 0, 1],
])
print("Kernel:")
print(kernel)
# výpočet konvoluce
filtered = convolve(ascent, kernel)
# zobrazení výsledku
plt.imshow(filtered, cmap="gray")
plt.title("2D convolution")
# uložení grafu s průběhem signálu
plt.savefig("convolve_2d_4.png")
# zobrazení grafu
plt.show()
Nyní bude výsledek vypadat následovně:
Obrázek 4: Hledání hran v obrázku s využitím konvolučního filtru.
Sofistikovanější konvoluční jádra
Knihovna SciPy nabízí v podbalíčku nazvaném ndimage filtry pro odstranění šumu i pro zvýraznění hran. Jedním z těchto filtrů je i výše zmíněný Gaussovský filtr, který je vypočten a aplikován funkcí gaussian_filter:
gaussian_filter(input, sigma, order=0, output=None, mode='reflect', cval=0.0, truncate=4.0, *, radius=None, axes=None)
Multidimensional Gaussian filter.
Parameters
----------
input : array_like
The input array.
sigma : scalar or sequence of scalars
Standard deviation for Gaussian kernel. The standard
deviations of the Gaussian filter are given for each axis as a
sequence, or as a single number, in which case it is equal for
all axes.
order : int or sequence of ints, optional
The order of the filter along each axis is given as a sequence
of integers, or as a single number. An order of 0 corresponds
to convolution with a Gaussian kernel. A positive order
corresponds to convolution with that derivative of a Gaussian.
output : array or dtype, optional
The array in which to place the output, or the dtype of the
returned array. By default an array of the same dtype as input
will be created.
mode : str or sequence, optional
The `mode` parameter determines how the input array is extended
when the filter overlaps a border. By passing a sequence of modes
with length equal to the number of dimensions of the input array,
different modes can be specified along each axis. Default value is
'reflect'. The valid values and their behavior is as follows:
Otestujme si aplikaci tohoto filtru na obrázek (matici) 6×6 pixelů:
import numpy as np
from scipy import ndimage
input_matrix = np.array([
[5, 5, 5, 5, 5, 5],
[5, 0, 5, 5, 5, 5],
[5, 5, 5, 5, 5, 5],
[5, 5, 5, 5, 5, 5],
[5, 5, 5, 5,10, 5],
[5, 5, 5, 5, 5, 5],
])
# aplikace filtru
filtered = ndimage.gaussian_filter(input_matrix, sigma=0.5)
print(filtered)
print()
# aplikace filtru
filtered2 = ndimage.gaussian_filter(input_matrix, sigma=0.7)
print(filtered2)
Výsledkem je do různé míry „rozmazaný“ pixel s příliš velkou nebo naopak s příliš malou hodnotou:
[[4 4 4 4 5 5] [4 1 4 4 5 5] [4 4 4 4 5 5] [4 4 4 4 5 5] [5 5 5 5 7 5] [5 5 5 5 5 5]] [[4 3 4 4 4 5] [4 3 4 4 4 5] [4 3 4 4 4 5] [4 4 4 5 5 5] [4 4 4 5 6 5] [5 5 5 5 5 5]]
Gaussovský filtr: vliv hodnoty sigma na provedenou operaci
V Gaussově funkci, ze které je Guassovský filtr odvozen, určuje parametr sigma šířku či strmost „zvonovité“ části křivky. Čím menší je tento parametr, tím užší zvonovitá část bude. Při aplikaci filtru to znamená, že výsledný obraz bude více zaostřený. To si ostatně můžeme otestovat v praxi.
Nejprve nastavíme parametr sigma na hodnotu 2.0:
import numpy as np
import scipy.datasets as datasets
from scipy import ndimage
import matplotlib.pyplot as plt
# načtení matice
ascent = datasets.ascent()
# aplikace filtru
blurred = ndimage.gaussian_filter(ascent, sigma=2.0)
# zobrazení výsledku, změna měřítka
plt.imshow(blurred, cmap="gray")
plt.title("Gaussian filter")
# uložení matice do rastrového obrázku
plt.savefig("gaussian_filter_1.png")
# zobrazení grafu
plt.show()
Výsledek:
Obrázek 5: Gaussův filtr.
Většího rozostření dosáhneme zvětšením hodnoty sigma:
import numpy as np
import scipy.datasets as datasets
from scipy import ndimage
import matplotlib.pyplot as plt
# načtení matice
ascent = datasets.ascent()
# aplikace filtru
blurred = ndimage.gaussian_filter(ascent, sigma=5.0)
# zobrazení výsledku, změna měřítka
plt.imshow(blurred, cmap="gray")
plt.title("Gaussian filter")
# uložení matice do rastrového obrázku
plt.savefig("gaussian_filter_2.png")
# zobrazení grafu
plt.show()
Výsledek:
Obrázek 6: Gaussův filtr.
Laplaceův filtr
Laplaceův filtr (Laplacián, i když striktně chápáno je to nesprávné jméno) slouží ke zvýraznění změn v obrázku (tedy například k „doostření“), popř. jako jeden z kroků při detekci hran, které se v obrázku nachází. Taktéž se při typické implementaci jedná o konvoluční filtr, což znamená, že se jádro filtru (kernel) postupně aplikuje na všechny pixely zdrojového obrázku i na jejich okolí.
Aplikace Laplaceova filtru na obrázek je jednoduchá: použijeme funkci ndimage.laplace:
laplace(input, output=None, mode='reflect', cval=0.0, *, axes=None)
N-D Laplace filter based on approximate second derivatives.
Parameters
----------
input : array_like
The input array.
output : array or dtype, optional
The array in which to place the output, or the dtype of the
returned array. By default an array of the same dtype as input
will be created.
mode : str or sequence, optional
The `mode` parameter determines how the input array is extended
when the filter overlaps a border. By passing a sequence of modes
with length equal to the number of dimensions of the input array,
different modes can be specified along each axis. Default value is
'reflect'. The valid values and their behavior is as follows:
Vyzkoušejme si, jak filtr reaguje na dvojici změn v obrázku 6×6 hodnot: konkrétně na nulový prvek a naopak na prvek s hodnotou 10, když průměr je 5:
import numpy as np
from scipy import ndimage
input_matrix = np.array([
[5, 5, 5, 5, 5, 5],
[5, 0, 5, 5, 5, 5],
[5, 5, 5, 5, 5, 5],
[5, 5, 5, 5, 5, 5],
[5, 5, 5, 5,10, 5],
[5, 5, 5, 5, 5, 5],
])
# aplikace filtru
filtered = ndimage.laplace(input_matrix)
print(filtered)
Obě změny jsou ve výsledku zvýrazněny i s opačnými hodnotami v okolí:
[[ 0 -5 0 0 0 0] [ -5 20 -5 0 0 0] [ 0 -5 0 0 0 0] [ 0 0 0 0 5 0] [ 0 0 0 5 -20 5] [ 0 0 0 0 5 0]]
Aplikace Laplaceova filtru na rastrový obrázek
Přímá aplikace Laplaceova filtru na rastrový obrázek je realizovaná snadno: přímým voláním funkce ndimage.laplace s předáním obrázku do této funkce:
import numpy as np
import scipy.datasets as datasets
from scipy import ndimage
import matplotlib.pyplot as plt
# načtení matice
ascent = datasets.ascent()
# aplikace filtru
filtered = ndimage.laplace(ascent)
# zobrazení výsledku, změna měřítka
plt.imshow(filtered, cmap="gray")
plt.title("Laplace filter")
# uložení matice do rastrového obrázku
plt.savefig("laplace_filter_1.png")
# zobrazení grafu
plt.show()
Z výsledku je patrné, jakým způsobem jsou zvýrazněny všechny změny (vypočtené jako numerická derivace) v obrázku:
Obrázek 7: Laplaceův filtr.
Kombinace původního obrázku s výsledkem aplikace Laplaceova filtru
Dále je možné výsledek aplikace Laplaceova filtru přičíst nebo odečíst od původního obrázku. Přičtení bude mít za následek odstranění změn (či šumu), odečtení naopak zvýraznění těchto změn. Ostatně si to můžeme velmi snadno otestovat:
import numpy as np
import scipy.datasets as datasets
from scipy import ndimage
import matplotlib.pyplot as plt
# načtení matice
ascent = datasets.ascent()
# aplikace filtru
filtered = ndimage.laplace(ascent)
# zobrazení výsledku, změna měřítka
plt.imshow(ascent-filtered, cmap="gray")
plt.title("Laplace filter")
# uložení matice do rastrového obrázku
plt.savefig("laplace_filter_2.png")
# zobrazení grafu
plt.show()
Při pohledu na výsledný obrázek je patrné, že se všechny změny skutečně ještě více zvýraznily:
Obrázek 8: Kombinace původního obrázku a výsledku aplikace Laplaceova filtru.
Sobelův operátor
Třetím typem filtru, se kterým se dnes seznámíme, je Sobelův operátor, který lze použít pro detekci hran v určitém směru. Tento filtr kombinuje odstranění šumu v jednom směru s detekcí hran v kolmém směru. I tento filtr, resp. jeho konvoluční jádro, je možné reprezentovat maticí:
import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import convolve
import scipy.datasets as datasets
# načtení matice
ascent = datasets.ascent()
kernel = np.array([
[-1, 0, 1],
[-2, 0, 2],
[-1, 0, 1],
])
print("Kernel:")
print(kernel)
# výpočet konvoluce
filtered = convolve(ascent, kernel)
# zobrazení výsledku
plt.imshow(filtered, cmap="gray")
plt.title("2D convolution")
# uložení grafu s průběhem signálu
plt.savefig("convolve_2d_5.png")
# zobrazení grafu
plt.show()
Výsledkem je tento obrázek – zvýrazněny jsou vertikální hrany:
Obrázek 9: Sobelův operátor realizovaný konvolučním filtrem.
Matici s konvolučním jádrem ovšem můžeme i transponovat:
import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import convolve
import scipy.datasets as datasets
# načtení matice
ascent = datasets.ascent()
kernel = np.array([
[-1, -2, -1],
[ 0, 0, 0],
[ 1, 2, 1],
])
print("Kernel:")
print(kernel)
# výpočet konvoluce
filtered = convolve(ascent, kernel)
# zobrazení výsledku
plt.imshow(filtered, cmap="gray")
plt.title("2D convolution")
# uložení grafu s průběhem signálu
plt.savefig("convolve_2d_6.png")
# zobrazení grafu
plt.show()
Výsledek bude odlišný – zvýrazněny budou spíše hrany vodorovné:
Obrázek 10: Sobelův operátor realizovaný konvolučním filtrem.
Sobelův operátor nabízený knihovnou SciPy
I Sobelův operátor je nabízený přímo knihovnou SciPy. Jeho implementaci nalezneme opět v podbalíčku nazvaném ndimage:
sobel(input, axis=-1, output=None, mode='reflect', cval=0.0)
Calculate a Sobel filter.
Parameters
----------
input : array_like
The input array.
axis : int, optional
The axis of `input` along which to calculate. Default is -1.
output : array or dtype, optional
The array in which to place the output, or the dtype of the
returned array. By default an array of the same dtype as input
will be created.
mode : str or sequence, optional
The `mode` parameter determines how the input array is extended
when the filter overlaps a border. By passing a sequence of modes
with length equal to the number of dimensions of the input array,
different modes can be specified along each axis. Default value is
'reflect'. The valid values and their behavior is as follows:
Jak jsme si již ukázali v předchozích kapitolách pro Gaussův a Laplaceův filtr, pokusíme se o aplikaci Sobelova operátoru na matici 6×6 prvků, ve které mají pouze dva prvky odlišnou hodnotu (jeden příliš malou, druhý naopak příliš velkou):
import numpy as np
from scipy import ndimage
input_matrix = np.array([
[5, 5, 5, 5, 5, 5],
[5, 0, 5, 5, 5, 5],
[5, 5, 5, 5, 5, 5],
[5, 5, 5, 5, 5, 5],
[5, 5, 5, 5,10, 5],
[5, 5, 5, 5, 5, 5],
])
# aplikace filtru
filtered = ndimage.sobel(input_matrix, axis=0)
print(filtered)
print()
# aplikace filtru
filtered2 = ndimage.sobel(input_matrix, axis=1)
print(filtered2)
V prvním případě se naleznou změny ve vertikálním směru:
[[ -5 -10 -5 0 0 0] [ 0 0 0 0 0 0] [ 5 10 5 0 0 0] [ 0 0 0 5 10 5] [ 0 0 0 0 0 0] [ 0 0 0 -5 -10 -5]]
Ve druhém případě se změny naleznou ve směru horizontálním:
[[ -5 0 5 0 0 0] [-10 0 10 0 0 0] [ -5 0 5 0 0 0] [ 0 0 0 5 0 -5] [ 0 0 0 10 0 -10] [ 0 0 0 5 0 -5]]
Aplikace Sobelova filtru na rastrový obrázek
Vyzkoušejme si nyní aplikaci funkce ndimage.sobel na testovací rastrový obrázek z původní datové sady knihovny SciPy:
import numpy as np
import scipy.datasets as datasets
from scipy import ndimage
import matplotlib.pyplot as plt
# načtení matice
ascent = datasets.ascent()
# aplikace filtru
filtered = ndimage.sobel(ascent, axis=0)
# zobrazení výsledku, změna měřítka
plt.imshow(filtered, cmap="gray")
plt.title("Sobel operator")
# uložení matice do rastrového obrázku
plt.savefig("sobel_operator_1.png")
# zobrazení grafu
plt.show()
Výsledek přímé aplikace Sobelova operátoru dopadne následovně:
Obrázek 11: Přímý výsledek aplikace Sobelova operátoru.
Dtto, ovšem nyní bude filtr otočen o 90° (viz parametr axis=1):
import numpy as np
import scipy.datasets as datasets
from scipy import ndimage
import matplotlib.pyplot as plt
# načtení matice
ascent = datasets.ascent()
# aplikace filtru
filtered = ndimage.sobel(ascent, axis=1)
# zobrazení výsledku, změna měřítka
plt.imshow(filtered, cmap="gray")
plt.title("Sobel operator")
# uložení matice do rastrového obrázku
plt.savefig("sobel_operator_2.png")
# zobrazení grafu
plt.show()
Výsledek:
Obrázek 12: Přímý výsledek aplikace Sobelova operátoru.
Kombinace původního obrázku a výsledku aplikace Sobelova operátoru
V předchozím textu jsme si ukázali, jak lze zkombinovat původní obrázek s výsledkem aplikace Laplaceova filtru. Totéž ovšem můžeme provést i s původním obrázkem a výsledkem výpočtu Sobelova operátoru:
import numpy as np
import scipy.datasets as datasets
from scipy import ndimage
import matplotlib.pyplot as plt
# načtení matice
ascent = datasets.ascent()
# aplikace filtru
filtered = ndimage.sobel(ascent, axis=0)
# zobrazení výsledku, změna měřítka
plt.imshow(ascent - filtered, cmap="gray")
plt.title("Sobel operator")
# uložení matice do rastrového obrázku
plt.savefig("sobel_operator_3.png")
# zobrazení grafu
plt.show()
Výsledek:
Obrázek 13: Kombinace výsledku aplikace Sobelova operátoru s původním obrázkem.
Prakticky tentýž příklad, ovšem s otočeným filtrem (opět viz parametr axis=1):
import numpy as np
import scipy.datasets as datasets
from scipy import ndimage
import matplotlib.pyplot as plt
# načtení matice
ascent = datasets.ascent()
# aplikace filtru
filtered = ndimage.sobel(ascent, axis=1)
# zobrazení výsledku, změna měřítka
plt.imshow(ascent - filtered, cmap="gray")
plt.title("Sobel operator")
# uložení matice do rastrového obrázku
plt.savefig("sobel_operator_4.png")
# zobrazení grafu
plt.show()
Otestování filtrů na zašuměném obrázku
Vykoušejme si nyní filtraci obrázku, který je zašuměný. Použijeme obrázek s povrchem měsíce, který jsme si ukázali již minule:
Obrázek 14: Zdroj s mnoha vadami (zobrazte si originál!).
Aplikovat budeme Gaussovský filtr s hodnotou sigma rostoucí od 0,5 do 2,0:
import numpy as np
from scipy import fftpack
from scipy import ndimage
import matplotlib.pyplot as plt
original = plt.imread("moonlanding.png").astype(float)
# aplikace filtru
blurred = ndimage.gaussian_filter(original, sigma=0.5)
# zobrazení výsledku
plt.imshow(blurred, cmap="gray")
# uložení matice do rastrového obrázku
plt.savefig("gaussian_filter_4.png")
# zobrazení grafu
plt.show()
import numpy as np
from scipy import fftpack
from scipy import ndimage
import matplotlib.pyplot as plt
original = plt.imread("moonlanding.png").astype(float)
# aplikace filtru
blurred = ndimage.gaussian_filter(original, sigma=1)
# zobrazení výsledku
plt.imshow(blurred, cmap="gray")
# uložení matice do rastrového obrázku
plt.savefig("gaussian_filter_5.png")
# zobrazení grafu
plt.show()
import numpy as np
from scipy import fftpack
from scipy import ndimage
import matplotlib.pyplot as plt
original = plt.imread("moonlanding.png").astype(float)
# aplikace filtru
blurred = ndimage.gaussian_filter(original, sigma=2)
# zobrazení výsledku
plt.imshow(blurred, cmap="gray")
# uložení matice do rastrového obrázku
plt.savefig("gaussian_filter_6.png")
# zobrazení grafu
plt.show()
Výsledky aplikace Gaussovského filtru
Všechny následující obrázky je zapotřebí si nechat zobrazit v původní velikosti (jinak se aplikují filtry při zmenšování obrázků na plochu Roota):
Obrázek 15: Výsledek aplikace Gaussovského filtru pro hodnotu sigma=0,5.
Obrázek 16: Výsledek aplikace Gaussovského filtru pro hodnotu sigma=1.
Obrázek 17: Výsledek aplikace Gaussovského filtru pro hodnotu sigma=2.
Repositář s demonstračními příklady
Všechny demonstrační příklady popsané v tomto článku naleznete i v repositáři https://github.com/tisnik/most-popular-python-libs. Následují odkazy na jednotlivé příklady:
Odkazy na Internetu
- SciPy homepage
https://scipy.org/ - SciPy (Wikipedia)
https://en.wikipedia.org/wiki/SciPy - The Hertzsprung–Russell diagram
https://scipython.com/book2/chapter-9-data-analysis-with-pandas/problems/p92/the-hertzsprung-russell-diagram/ - Linear algebra (scipy.linalg)
https://docs.scipy.org/doc/scipy/reference/linalg.html - Frequently Asked Questions – SciPy
https://scipy.org/faq/ - SciPy – Introduction
https://www.tutorialspoint.com/scipy/scipy_introduction.htm - LAPACK — Linear Algebra PACKage
https://www.netlib.org/lapack/ - LAPACK (Wikipedia)
https://en.wikipedia.org/wiki/LAPACK - LAPACK na GitHubu
https://github.com/Reference-LAPACK/lapack - SciPy in Python
https://pythonguides.com/scipy/ - scipy.linalg.det
https://docs.scipy.org/doc/scipy/reference/generated/scipy.linalg.det.html#scipy.linalg.det - scipy.linalg.inv
https://docs.scipy.org/doc/scipy/reference/generated/scipy.linalg.inv.html#scipy.linalg.inv - scipy.linalg.solve
https://docs.scipy.org/doc/scipy/reference/generated/scipy.linalg.inv.html#scipy.linalg.inv - Algebra
https://cs.wikipedia.org/wiki/Algebra - Lineární algebra
https://cs.wikipedia.org/wiki/Line%C3%A1rn%C3%AD_algebra - Lineární rovnice
https://cs.wikipedia.org/wiki/Line%C3%A1rn%C3%AD_rovnice - Soustava lineárních rovnic
https://cs.wikipedia.org/wiki/Soustava_line%C3%A1rn%C3%ADch_rovnic - Norma matice
https://cs.wikipedia.org/wiki/Norma_matice - Matrix norm
https://en.wikipedia.org/wiki/Matrix_norm - Norma (vektoru)
https://cs.wikipedia.org/wiki/Norma_(matematika) - Frobeniův skalární součin
https://cs.wikipedia.org/wiki/Frobeni%C5%AFv_skal%C3%A1rn%C3%AD_sou%C4%8Din - BLAS (Basic Linear Algebra Subprograms)
https://www.netlib.org/blas/ - Basic Linear Algebra Subprograms (Wikipedia)
https://en.wikipedia.org/wiki/Basic_Linear_Algebra_Subprograms - Operace s daty uloženými v binárních souborech v knihovnách NumPy a Pandas
https://www.root.cz/clanky/operace-s-daty-ulozenymi-v-binarnich-souborech-v-knihovnach-numpy-a-pandas/ - Operace s daty uloženými v binárních souborech v knihovnách NumPy a Pandas (dokončení)
https://www.root.cz/clanky/operace-s-daty-ulozenymi-v-binarnich-souborech-v-knihovnach-numpy-a-pandas-dokonceni/ - NumPy Home Page
http://www.numpy.org/ - NumPy v1.10 Manual
http://docs.scipy.org/doc/numpy/index.html - NumPy (Wikipedia)
https://en.wikipedia.org/wiki/NumPy - OpenBLAS: An optimized BLAS library
https://www.openblas.net/ - Integrovaná vývojová prostředí ve Fedoře: IPython a IPython Notebook
http://mojefedora.cz/integrovana-vyvojova-prostredi-ve-fedore-ipython-a-ipython-notebook/ - Integrovaná vývojová prostředí ve Fedoře: praktické použití IPython Notebooku a knihovny Numpy
http://mojefedora.cz/integrovana-vyvojova-prostredi-ve-fedore-prakticke-pouziti-ipython-notebooku-a-knihovny-numpy/ - Integrovaná vývojová prostředí ve Fedoře: praktické použití IPython Notebooku a knihovny Numpy (2.část)
http://mojefedora.cz/integrovana-vyvojova-prostredi-ve-fedore-prakticke-pouziti-ipython-notebooku-a-knihovny-numpy-2-cast/ - Integrovaná vývojová prostředí ve Fedoře: vykreslování grafů s využitím knihoven Numpy a matplotlib
http://mojefedora.cz/integrovana-vyvojova-prostredi-ve-fedore-vykreslovani-grafu-s-vyuzitim-knihoven-numpy-a-matplotlib/ - Integrovaná vývojová prostředí ve Fedoře: vykreslování grafů s využitím knihoven Numpy a matplotlib (2.část)
http://mojefedora.cz/integrovana-vyvojova-prostredi-ve-fedore-vykreslovani-grafu-s-vyuzitim-knihoven-numpy-a-matplotlib-2-cast/ - Piecewise linear interpolation
https://docs.scipy.org/doc//scipy/tutorial/interpolate/1D.html - Statistical functions (scipy.stats)
https://docs.scipy.org/doc/scipy/reference/stats.html - scipy.stats.linregress
https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.linregress.html - numpy.poly1d
https://numpy.org/doc/stable/reference/generated/numpy.poly1d.html - scipy.optimize.curve_fit
https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.curve_fit.html#scipy.optimize.curve_fit - scipy.interpolate.make_smoothing_spline
https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.make_smoothing_spline.html#scipy.interpolate.make_smoothing_spline - Famous Curves Index
https://mathshistory.st-andrews.ac.uk/Curves/ - Curve (Wikipedia)
https://en.wikipedia.org/wiki/Curve - Mathematical curves
https://www.2dcurves.com/index.html - Curves (Wolfram MathWorld)
https://mathworld.wolfram.com/topics/Curves.html - Smooth Curve (Wolfram MathWorld)
https://mathworld.wolfram.com/SmoothCurve.html - Spirals (Wolfram MathWorld)
https://mathworld.wolfram.com/topics/Spirals.html - An Interactive Introduction to Splines
https://ibiblio.org/e-notes/Splines/Intro.htm - Algebraic curve
https://en.wikipedia.org/wiki/Algebraic_curve - Transcendental curve
https://en.wikipedia.org/wiki/Transcendental_curve - Algebraic Curves
https://mathworld.wolfram.com/topics/AlgebraicCurves.html - Elliptic Curves
https://mathworld.wolfram.com/topics/EllipticCurves.html - Curves we (mostly) don't learn in high school (and applications)
https://www.youtube.com/watch?v=3izFMB91K_Q - Catenary arch
https://en.wikipedia.org/wiki/Catenary_arch - Parabolic arch
https://en.wikipedia.org/wiki/Parabolic_arch - Wattova křivka
https://www.geogebra.org/m/gNh4bW9r - Fifty Famous Curves, Lots of Calculus Questions, And a Few Answers
https://elepa.files.wordpress.com/2013/11/fifty-famous-curves.pdf - Faux, I.D. a Pratt, M.J.: Computational Geometry for Design and Manufacture,
Ellis Horwood Ltd., Wiley & Sons, 1979 - Wallace A.: Differential Topology,
Benjamin/Cummings Co., Reading, Massachussetts, USA, 1968 - Glossary of Bridge Terminology
http://sdrc.lib.uiowa.edu/eng/bridges/WaddellGlossary/GlossC.htm - Brachistochrona
https://cs.wikipedia.org/wiki/Brachistochrona - Missions: Cassini
https://solarsystem.nasa.gov/missions/cassini/overview/ - Giovanni Domenico Cassini
https://en.wikipedia.org/wiki/Giovanni_Domenico_Cassini - Cassini Ovals
https://mathworld.wolfram.com/CassiniOvals.html - Geocentrismus
https://cs.wikipedia.org/wiki/Geocentrismus - Who was Giovanni Cassini?
https://www.universetoday.com/130823/who-was-giovanni-cassini/ - Special plane curves
http://xahlee.info/SpecialPlaneCurves_dir/ConicSections_dir/conicSections.html - Interpolace
https://mathonline.fme.vutbr.cz/pg/Algoritmy/05_APROX_KRIVKY.htm - Lagrange Polynomial Interpolation
https://pythonnumericalmethods.berkeley.edu/notebooks/chapter17.04-Lagrange-Polynomial-Interpolation.html - Python Program for Lagrange Interpolation Method (with Output)
https://www.codesansar.com/numerical-methods/python-program-lagrange-interpolation-method.htm - Smooth Paths Using Catmull-Rom Splines
https://qroph.github.io/2018/07/30/smooth-paths-using-catmull-rom-splines.html - Lecture 11: Linear Interpolation Again – Bézier Curves
http://www.math.kent.edu/~reichel/courses/intr.num.comp.1/fall09/lecture12/bez.pdf - Geometrie/Úvod do křivek
https://cs.wikibooks.org/wiki/Geometrie/%C3%9Avod_do_k%C5%99ivek - B-Spline Curves and Surfaces (1)
http://www.cad.zju.edu.cn/home/zhx/GM/006/00-bscs1.pdf - Praktické ukázky možností aplikace Mandelbulber při tvorbě animací
https://www.root.cz/clanky/prakticke-ukazky-moznosti-aplikace-mandelbulber-pri-tvorbe-animaci/ - Kochanek–Bartels spline
https://en.wikipedia.org/wiki/Kochanek%E2%80%93Bartels_spline - class KochanekBartels
https://splines.readthedocs.io/en/latest/_modules/splines.html#KochanekBartels - Konvoluce
https://cs.wikipedia.org/wiki/Konvoluce - Korelace
https://cs.wikipedia.org/wiki/Korelace - Fourierova transformace
https://cs.wikipedia.org/wiki/Fourierova_transformace - Lanczos resampling
https://en.wikipedia.org/wiki/Lanczos_resampling - Obrázek se schodištěm
https://pixnio.com/people/accent-to-the-top - Obrázek s mývalem
https://pixnio.com/fauna-animals/raccoons/raccoon-procyon-lotor - Sample-rate conversion
https://en.wikipedia.org/wiki/Sample-rate_conversion - Seriál Grafické formáty
https://www.root.cz/serialy/graficke-formaty/ - JPEG – král rastrových grafických formátů?
https://www.root.cz/clanky/jpeg-kral-rastrovych-grafickych-formatu/ - Ztrátová komprese obrazových dat pomocí JPEG
https://www.root.cz/clanky/ztratova-komprese-obrazovych-dat-pomoci-jpeg/ - Programujeme JPEG: transformace a podvzorkování barev
https://www.root.cz/clanky/programujeme-jpeg-transformace-a-podvzorkovani-barev/ - Programujeme JPEG: diskrétní kosinová transformace (DCT)
https://www.root.cz/clanky/programujeme-jpeg-diskretni-kosinova-transformace-dct/ - Programujeme JPEG: Kvantizace DCT koeficientů
https://www.root.cz/clanky/programujeme-jpeg-kvantizace-dct-koeficientu/ - Programujeme JPEG: Huffmanovo kódování kvantovaných DCT složek
https://www.root.cz/clanky/programujeme-jpeg-huffmanovo-kodovani-kvantovanych-dct-slozek/ - Programujeme JPEG: Interní struktura souborů typu JFIF/JPEG
https://www.root.cz/clanky/programujeme-jpeg-interni-struktura-souboru-typu-jfifjpeg/ - Programujeme JPEG: Načtení informací ze souborů typu JFIF/JPEG
https://www.root.cz/clanky/programujeme-jpeg-nacteni-informaci-ze-souboru-typu-jfifjpeg/ - Programujeme JPEG: Progresivní JPEG a informace EXIF
https://www.root.cz/clanky/programujeme-jpeg-progresivni-jpeg-a-informace-exif/ - The Fourier Analysis –The Fast Fourier Transform (FFT) Method
https://www.electronics-lab.com/article/the-fourier-analysis-the-fast-fourier-transform-fft-method/ - Understanding the output of FFT
https://howthefouriertransformworks.com/understanding-the-output-of-an-fft/ - What factors go into choosing DCT type 1 over type 2 or type 3 etc?
https://dsp.stackexchange.com/questions/31611/what-factors-go-into-choosing-dct-type-1-over-type-2-or-type-3-etc - The Discrete Cosine Transform (DCT)
https://ccrma.stanford.edu/~jos/mdft/Discrete_Cosine_Transform_DCT.html - Eulerův vzorec
https://cs.wikipedia.org/wiki/Euler%C5%AFv_vzorec - Komplexní analýza
https://cs.wikipedia.org/wiki/Komplexn%C3%AD_anal%C3%BDza - What is the difference between a Fourier transform and a cosine transform?
https://dsp.stackexchange.com/questions/13/what-is-the-difference-between-a-fourier-transform-and-a-cosine-transform - Two-dimensional Discrete Cosine Transform as a Linear Transformation
https://fairyonice.github.io/2D-DCT.html - fft2 (Matlab)
https://www.mathworks.com/help/matlab/ref/fft2.html - Image denoising by FFT
https://scipy-lectures.org/intro/scipy/auto_examples/solutions/plot_fft_image_denoise.html - Discrete sine transform
https://en.wikipedia.org/wiki/Discrete_sine_transform - Diskrétní sinová transformace: demo
https://www.desmos.com/calculator/k5jlr0ykzw
