Widzenie maszynowe cz. 1

Przetwarzanie obrazów w Pythonie

Widzenie maszynowe to fascynująca i błyskawicznie się rozwijająca dziedzina techniki. Pozwala wyposażyć systemy techniczne w takie możliwości jak automatyczna analiza tekstu, generowanie rozszerzonej rzeczywistości czy rozpoznawanie twarzy.

Takimi właśnie tematami będziemy się zajmować w tej serii wpisów. Obecnie najwygodniejszym narzędziem do rozwiązywania wymienionych problemów wydaje się być Pythona. Dlatego zaczniemy od krótkiej demonstracji jak wykorzystać go do prostych operacji na obrazach.

Skąd wziąć Pythona?

Siłą Pythona w budowaniu systemów widzenia maszynowego jest dostęp do mnóstwa przydatnych pakietów. Żeby nie instalować każdego z nich osobno można zainstalować gotową dystrybucję Pythona o nazwie Anaconda. Jak to zrobić opisałem w innym wpisie.

Wszystkie przykłady, które będziemy analizować można ściągnąć w formie notatnika Jupytera korzystając z tego linku. Możesz pracować w tym notatniku lub utworzyć nowy (tworzenie notatników również znajdziesz we wpisie poświęconym instalacji Anacondy). Możesz też utworzyć skrypt Pythona w dowolnym edytorze tekstu i uruchomić go z konsoli systemu operacyjnego. Pamiętaj, że inaczej będzie się wtedy zachowywać biblioteka Matplotlib, której będziemy używać do wyświetlania obrazów. W szczególności nic nie zostanie wyświetlone bez wywołania funkcji plt.show().

Import niezbędnych bibliotek

Zaczynamy od importu bibliotek potrzebnych nam do wykonania wszystkich ćwiczeń:

import numpy as np
import PIL
import matplotlib.pyplot as plt
import scipy.signal

Biblioteki, z których korzystamy to:

  • NumPy – jest to bardzo przydatna i bardzo popularna biblioteka do obliczeń numerycznych. Bazuje na niej też dużo bibliotek do analizy danych, uczenia maszynowego, sztucznej inteligencji czy właśnie przetwarzania obrazów.
  • PIL (Python Image Library) – biblioteka zawierające różne funkcje do przetwarzania obrazów. Jest mniej popularna od np. OpenCV, ale instaluje się razem z Anacondą, więc na razie z niej skorzystamy. Będzie nam potrzebna tylko do wczytania obrazu z dysku.
  • Matplotlib – biblioteka zawierająca różne przydatne funkcje do rysowania obrazów i wykresów. W swojej składni stara się bazować na funkcjach znanych z MATLABa.
  • SciPy signal processing – moduł wchodzący w skład biblioteki SciPy. Zawiera funkcję do cyfrowego przetwarzania sygnałów. My użyjemy jej do rozmycia obrazu za pomocą filtru splotowego.

Ładowanie i wyświetlania obrazu

Po zaimportowaniu bibliotek możemy wczytać z dysku obraz i wyświetlić go za pomocą biblioteki Matplotlib:

im_pil = PIL.Image.open('city.jpg')
im = np.array(im_pil)
plt.imshow(im)
plt.show()

W pierwszej linii wczytujemy obraz za pomocą biblioteki PIL. Jako argument do funkcji open musisz podać oczywiście swoją ścieżkę do obrazu.

W drugiej linii formatujemy obraz wczytany przez PIL tworząc obiekt klasy Ndarray używanej przez NumPy.

W trzeciej linii wyświetlamy obraz za pomocą biblioteki Matplotlib.

Wywołaniu funkcji show() w ostatniej linii wyświetli obraz. Nie trzeba tego robić jeżeli korzystamy z notatnika Jupytera.

Jeżeli wszystko zrobiliśmy poprawnie to zobaczymy następujący obraz:

Konwersja do skali szarości

W wielu zastosowaniach operuje się na obrazach w skali szarości. Obraz kolorowy jest reprezentowany w naszym przykładzie jako trójwymiarowa tablica, w której pierwszy wymiar oznacza numer wiersza, drugi numer kolumny, a trzeci numer jednego z trzech kanałów koloru (czerwony, zielony lub niebieski). Żeby wygenerować obraz w skali szarości możemy np. uśrednić wszystkie składowe koloru:

im_gray = np.mean(im, axis=2)
plt.imshow(im_gray, cmap='gray')

W pierwszej linii wykorzystujemy funkcję mean to uśrednienia obrazu. Argument axis=2 oznacza, że uśrednianie przeprowadzamy po trzecim wymiarze (pierwszy wymiar ma numer 0), który jak już wiemy oznacza kanał koloru.

Argument cmap=’gray’ spowoduje, że Matplotlib nie zastosuje tzw. pseudokolorów podczas wizualizacji obrazu bez trzech kanałów koloru.

W efekcie działania kody zobaczymy przekonwertowany obraz:

Progowanie obrazu

Innym przykładem prostej operacji na obrazie jest jego progowanie. Zamieniamy nasz obraz, którego piksele mogą przyjmować wartości od 0 do 255 na obraz, którego piksele przyjmują tylko jedną z dwóch wartości (tzw. obraz binarny). Możemy przyjąć, że wszystkie piksele o wartościach powyżej pewnej liczby przyjmą w naszym obrazie binarnym wartość 1, a pozostałe wartość 0. Za pomocą biblioteki NumPy można to zrobić bardzo prosto: 

thresh = 160
im_thresh = im_gray > thresh
plt.imshow(im_thresh, cmap='gray')

Jako próg przyjęliśmy tutaj wartość 160. W naszym przykładzie pozwala ona mniej więcej oddzielić niebo od reszty obrazu. Matplotlib prawidłowo wyświetli obraz binarny przedstawiając piksele o wartości 0 jako czarne, a 1 jako białe:

Filtracja splotowa

Na koniec wykonamy filtrację splotową obrazu. Sama filtracja splotowa ma bardzo wiele zastosowań i stanowi jedną z podstawowych technik przetwarzania obrazu. Jest to jednak temat bardzo szeroki. Nie będziemy się w niego wgłębiać. Wykonamy tylko prosty przykład wykorzystania biblioteki Scipy do rozmycia obrazu. Odpowiedni kod wygląda następująco:

#Liczba pikseli do lokalnego uśredniania
filter_size = 3

#Maska filtru
mask = np.ones((filter_size, filter_size))

#Zwizualizujmy sobie maskę
print('Maska filtru: '+str(mask))

#Filtracja obrazu
im_filtered = scipy.signal.convolve2d(im_gray, mask)

#Narysujmy obraz oryginalny i po filtracji
plt.imshow(im_gray,  cmap='gray')
plt.title('Obraz oryginalny')

plt.figure() #Potrzebujemy utworzyć nowe okno, żeby nie nadpisać poprzednio wyświetlonego obrazu
plt.imshow(im_filtered,  cmap='gray')
plt.title('Obraz rozmyty')

Ponieważ o filtracji splotowej można się rozpisać bardzo szeroko to nie będę wyjaśniał kodu powyżej. Dodałem do niego tylko trochę komentarzy. W wyniku jego działania powinniśmy uzyskać rozmyty obraz:

Możesz poeksperymentować i sprawdzić jak na wygląd obrazu wpłynie zmiana wartości zmiennej filter_size.

Podsumowanie

Zobaczyliśmy jak wykorzystać możliwości Pythona do realizacji prostych operacji przetwarzających obrazy i jak wizualizować wyniki takich operacji. W kolejnej części spróbujemy za pomocą analizy koloru zaimplementować bardzo prostą aplikację widzenia maszynowego.

Do zobaczenia!

Maciej Kraszewski

Maciej Kraszewski

Inżynier, menedżer R&D i nauczyciel akademicki. Uwielbiam zajmować się tworzeniem nowych technologii, zdobywaniem nowej wiedzy i dzieleniem się swoim doświadczeniem z innymi. Specjalizuję się w zagadnieniach przetwarzania obrazu i widzenia maszynowego.
Szukasz dobrych materiałów o projektowaniu elektroniki?

Załóż darmowe konto na naszej platformie i odbierz pakiet materiałów edukacyjnych.

Zakładając konto zgadzasz się na przesyłanie Ci treści marketingowych przez IT20 sp. z o.o. zgodnie z dostępną na stronie Polityką Prywatności. Możesz wycofać zgodę w każdej chwili.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

Szukasz dobrych materiałów o projektowaniu elektroniki?

Załóż darmowe konto na naszej platformie i odbierz pakiet materiałów edukacyjnych.

Zakładając konto zgadzasz się na przesyłanie Ci treści marketingowych przez IT20 sp. z o.o. zgodnie z dostępną na stronie Polityką Prywatności. Możesz wycofać zgodę w każdej chwili.

Zapisz się na listę mailową i odbierz swoje bonusy!

Więcej treści na temat elektroniki i robotyki, darmowe e-booki i dostęp do minikursów on-line. Otrzymasz to wszystko zapisując się na naszą listę mailową.