Buduj rewolucje i zmierz się

1. Zanim zaczniesz

Dzięki nim dowiesz się więcej o powodach splotu i ich znaczeniu w scenariuszach wizualnych.

W poprzednim ćwiczeniu z programowania udało Ci się utworzyć prostą sieć neuronową (DNN) na potrzeby komputerowego rozpoznawania produktów modowych. Ograniczyliśmy dostęp do niego, ponieważ wymagany był tylko element stroju. Musi on być wyśrodkowany.

Oczywiście nie jest to realistyczny scenariusz. Dokładna nazwa wyróżniająca ubrania może być rozpoznawana na zdjęciach za pomocą innych przedmiotów lub w miejscach, w których jest ona umieszczona z przodu i na środku. Aby to zrobić, musisz używać splotu.

Wymagania wstępne

Ćwiczenia z programowania są oparte na zadaniach rozpoczętych w 2 poprzednich częściach: Witaj, świecie – „świat i systemy uczące się” i Utwórz model wizyjny. Zanim przejdziesz dalej, wykonaj te ćwiczenia.

Czego się nauczysz:

  • Co to są sploty
  • Jak utworzyć mapę cech
  • Czym jest pula basenowa

Co stworzysz

  • Mapa funkcji obrazu

Czego potrzebujesz

Kod do reszty ćwiczeń z programowania znajdziesz w Colab.

Musisz też mieć zainstalowane narzędzie TensorFlow, a także biblioteki zainstalowane w poprzednim kursie.

2. Co to są sploty?

Splot to filtr, który przekazuje obraz, przetwarza go i wyodrębnia ważne cechy.

Załóżmy, że masz zdjęcie osoby w trampkach. Jak możesz wykryć, że na zdjęciu znajduje się trampka? Aby Twój program mógł „widzieć” tenisowy obraz, musisz wyodrębnić ważne funkcje i zamazać elementy składowe. Nazywa się to mapowaniem cech.

Teoretycznie proces mapowania cech jest teoretycznie prosty. Musisz przeskanować każdy piksel na zdjęciu, a następnie przyjrzeć się jego sąsiednim pikselom. Mnożysz wartości tych pikseli przez ich wagi w filtrze.

Przykład:

Splot obrazu

W tym przypadku określono matrycę splotu 3 x 3 (czyli jądro obrazu).

Obecna wartość piksela to 192. Wartość nowego piksela możesz obliczyć, analizując wartości sąsiadów, mnożąc je przez wartości określone w filtrze i określając ostateczną wartość nowego piksela.

Teraz czas zbadać, jak działają sploty, tworząc podstawowy splot na obrazie 2D w skali szarości.

Pokażemy to za pomocą obrazu z aplikacji SciPy. To ładny wbudowany obraz z wieloma kątami i liniami.

3. Rozpocznij programowanie

Najpierw zaimportuj niektóre biblioteki Pythona i obraz wejściowy:

import cv2
import numpy as np
from scipy import misc
i = misc.ascent()

Następnie użyj biblioteki Pyplot matplotlib, aby nakreślić obraz, tak aby wiedziała, jak wygląda:

import matplotlib.pyplot as plt
plt.grid(False)
plt.gray()
plt.axis('off')
plt.imshow(i)
plt.show()

edb460dd5397f7f4.png,

Jak widać, jest to zdjęcie schodów. Istnieje wiele funkcji, które można wypróbować izolować. Przykładem mogą być długie, pionowe linie.

Obraz jest przechowywany jako tablica NumPy, więc możemy utworzyć przekształcony obraz, kopiując tę tablicę. Zmienne rozmiaru_x i size_y przechowują wymiary obrazu, dzięki czemu możesz później zapętlić je.

i_transformed = np.copy(i)
size_x = i_transformed.shape[0]
size_y = i_transformed.shape[1]

4. Tworzenie macierzy zniekształcenia

Najpierw utwórz macierz splotu (lub jądro) jako tablicę 3 x 3:

# This filter detects edges nicely
# It creates a filter that only passes through sharp edges and straight lines. 
# Experiment with different values for fun effects.
#filter = [ [0, 1, 0], [1, -4, 1], [0, 1, 0]] 
# A couple more filters to try for fun!
filter = [ [-1, -2, -1], [0, 0, 0], [1, 2, 1]]
#filter = [ [-1, 0, 1], [-2, 0, 2], [-1, 0, 1]]
 # If all the digits in the filter don't add up to 0 or 1, you 
# should probably do a weight to get it to do so
# so, for example, if your weights are 1,1,1 1,2,1 1,1,1
# They add up to 10, so you would set a weight of .1 if you want to normalize them
weight  = 1

Oblicz teraz piksele wyjściowe. Przekształć obraz w marginesy, pozostawiając 1 piksel piksela i pomnóż każdy sąsiad obecnego piksela przez wartość określoną w filtrze.

Oznacza to, że bieżący piksel sący nad nim i na lewo od niego jest mnożony przez lewy górny róg filtra w filtrze. Następnie pomnóż wynik przez wagę i upewnij się, że mieści się w zakresie od 0 do 255.

Na koniec wczytaj nową wartość do przekształconego obrazu:

for x in range(1,size_x-1):
  for y in range(1,size_y-1):
      output_pixel = 0.0
      output_pixel = output_pixel + (i[x - 1, y-1] * filter[0][0])
      output_pixel = output_pixel + (i[x, y-1] * filter[0][1])
      output_pixel = output_pixel + (i[x + 1, y-1] * filter[0][2])
      output_pixel = output_pixel + (i[x-1, y] * filter[1][0])
      output_pixel = output_pixel + (i[x, y] * filter[1][1])
      output_pixel = output_pixel + (i[x+1, y] * filter[1][2])
      output_pixel = output_pixel + (i[x-1, y+1] * filter[2][0])
      output_pixel = output_pixel + (i[x, y+1] * filter[2][1])
      output_pixel = output_pixel + (i[x+1, y+1] * filter[2][2])
      output_pixel = output_pixel * weight
      if(output_pixel<0):
        output_pixel=0
      if(output_pixel>255):
        output_pixel=255
      i_transformed[x, y] = output_pixel

5. Sprawdzanie wyników

Teraz wykreślić obraz, aby zobaczyć efekt przeniesienia filtra:

# Plot the image. Note the size of the axes -- they are 512 by 512
plt.gray()
plt.grid(False)
plt.imshow(i_transformed)
#plt.axis('off')
plt.show()   

48ff667b2df812ad.png

Przyjrzyj się poniższym wartościom filtrów i ich wpływowi na obraz.

Użycie [-1,0,1,-2,0,2,-1,0,1] daje bardzo wysoki zestaw pionowych linii:

Wykrywanie linii pionowych

Użycie [-1,-2,-1,0,0,0,1,2,1] daje poziome linie:

Wykrywanie linii poziomych

Poznaj różne wartości. Możesz też użyć filtrów o innych rozmiarach, np. 5 x 5 lub 7 x 7.

6. Informacje o puli

Znasz już podstawowe funkcje obrazu? Co chcesz zrobić? Jak używasz uzyskanej mapy cech do klasyfikowania obrazów?

Podobnie jak w przypadku rewolucji funkcja basenu bardzo pomaga w wykrywaniu funkcji. Warstwy warstwowe ograniczają ogólną ilość informacji na obrazie, zachowując funkcje wykryte jako obecne.

Istnieje wiele różnych typów pul, ale każdy używa tzw. maksymalnej (maks.) puli.

Retuszuj obraz na obrazie i w każdym momencie weź pod uwagę piksel oraz jego sąsiadów z prawej, poniżej i z prawej strony. Wybierz największą z nich (łącznie maksymalną) i załaduj ją na nowym zdjęciu. Dlatego nowy obraz będzie 1/4 rozmiaru starego. Maks. pula

7. Wpisz kod do pływania

Poniższy kod przedstawia pulę (2, 2). Uruchom go, aby zobaczyć dane wyjściowe.

Zobaczysz, że chociaż obraz jest 1/4 oryginalnego rozmiaru, zachował wszystkie funkcje.

new_x = int(size_x/2)
new_y = int(size_y/2)
newImage = np.zeros((new_x, new_y))
for x in range(0, size_x, 2):
  for y in range(0, size_y, 2):
    pixels = []
    pixels.append(i_transformed[x, y])
    pixels.append(i_transformed[x+1, y])
    pixels.append(i_transformed[x, y+1])
    pixels.append(i_transformed[x+1, y+1])
    pixels.sort(reverse=True)
    newImage[int(x/2),int(y/2)] = pixels[0]
 
# Plot the image. Note the size of the axes -- now 256 pixels instead of 512
plt.gray()
plt.grid(False)
plt.imshow(newImage)
#plt.axis('off')
plt.show()

1f5ebdafd1db2595

Zwróć uwagę na osie tego wykresu. Rozmiary obrazu to teraz 256 x 256, jedna czwarta jego pierwotnego rozmiaru, a wykryte funkcje zostały ulepszone, mimo że na zdjęciu jest teraz mniej danych.

8. Gratulacje

Udało Ci się stworzyć swój pierwszy model wizyjny. Aby dowiedzieć się więcej o tym, jak ulepszyć modele rozpoznawania obrazów, przeczytaj artykuł Tworzenie splotowych sieci neuronowych (CNN) w celu poprawy wzroku.