Jądro (przetwarzanie obrazu) - Kernel (image processing)

W przetwarzaniu obrazu , w jądrze , matrycy splotu lub maska jest mała matryca wykorzystywane do zatarcia, ostrzenia, wytłaczanie, detekcja krawędzi i innych. Osiąga się to poprzez splot pomiędzy jądrem a obrazem .

Detale

Ogólnym wyrazem splotu jest

gdzie jest filtrowany obraz, jest oryginalnym obrazem, jest jądrem filtra. Każdy element jądra filtru jest rozpatrywany przez i .


W zależności od wartości pierwiastków jądro może wywołać szeroki zakres efektów.

Operacja Jądro Wynik obrazu g(x,y)
Tożsamość Vd-Orig.png
Wykrywanie krawędzi Vd-Edge1.png
Vd-Edge2.png
Vd-Edge3.png
Wyostrzyć Vd-Sharp.png
Rozmycie pola
( znormalizowane )
Vd-Blur2.png
Rozmycie Gaussa 3 × 3
(przybliżenie)
Vd-Blur1.png
Rozmycie Gaussa 5 × 5
(przybliżenie)
Vd-Blur Gaussian 5x5.png
Maskowanie wyostrzające 5 × 5
Na podstawie rozmycia Gaussa
z wartością 1 i
progiem 0
(bez maski obrazu )




Vd-Unsharp 5x5.png

Powyższe to tylko kilka przykładów efektów, które można osiągnąć dzięki splataniu jąder i obrazów.

Początek

Pochodzenie to pozycja jądra, która znajduje się powyżej (konceptualnie) bieżącego piksela wyjściowego. Może to być poza samym jądrem, chociaż zwykle odpowiada jednemu z elementów jądra. W przypadku jądra symetrycznego pochodzenie jest zwykle elementem centralnym.

Skręt

Konwolucja to proces dodawania każdego elementu obrazu do jego lokalnych sąsiadów, ważonych przez jądro. Wiąże się to z formą splotu matematycznego . Wykonywana operacja macierzowa — splot — nie jest tradycyjnym mnożeniem macierzy, mimo że jest podobnie oznaczona przez *.

Na przykład, jeśli mamy dwie macierze trzy na trzy, pierwsza jest jądrem, a druga fragmentem obrazu, splot jest procesem odwracania zarówno wierszy, jak i kolumn jądra oraz mnożenia lokalnie podobnych wpisów i sumowania. Element o współrzędnych [2, 2] (czyli element centralny) wynikowego obrazu byłby ważoną kombinacją wszystkich wpisów macierzy obrazu, z wagami podanymi przez jądro:

Pozostałe wpisy byłyby podobnie ważone, gdzie umieszczamy środek jądra na każdym z punktów granicznych obrazu i obliczamy sumę ważoną.

Wartości danego piksela w obrazie wyjściowym są obliczane przez pomnożenie każdej wartości jądra przez odpowiednie wartości pikseli obrazu wejściowego. Można to opisać algorytmicznie za pomocą następującego pseudokodu:

for each image row in input image:
    for each pixel in image row:

        set accumulator to zero

        for each kernel row in kernel:
            for each element in kernel row:

                if element position  corresponding* to pixel position then
                    multiply element value  corresponding* to pixel value
                    add result to accumulator
                endif

         set output image pixel to accumulator
*odpowiadające piksele obrazu wejściowego są znalezione w stosunku do źródła jądra.

Jeśli jądro jest symetryczne, umieść środek (początek) jądra na bieżącym pikselu. Jądro nałoży się na sąsiednie piksele wokół punktu początkowego. Każdy element jądra należy pomnożyć przez wartość piksela, na którą się nakłada, a wszystkie otrzymane wartości należy zsumować. Ta wynikowa suma będzie nową wartością dla bieżącego piksela, który aktualnie nakłada się na środek jądra.

Jeśli jądro nie jest symetryczne, przed obliczeniem splotu jak powyżej należy je odwrócić zarówno wokół osi poziomej, jak i pionowej.

Ogólna postać splotu macierzy to

Obsługa krawędzi

Rozszerz obsługę krawędzi

Splot jądra zwykle wymaga wartości z pikseli znajdujących się poza granicami obrazu. Istnieje wiele metod obsługi krawędzi obrazu.

Rozszerzyć
Najbliższe piksele obramowania są koncepcyjnie rozciągnięte na tyle, na ile jest to konieczne, aby zapewnić wartości dla splotu. Piksele narożne są rozciągane w klinach 90°. Inne piksele krawędzi są rozciągane liniami.
Zawinąć
Obraz jest koncepcyjnie zawinięty (lub kafelkowany), a wartości są pobierane z przeciwległej krawędzi lub narożnika.
Lustro
Obraz jest koncepcyjnie lustrzany na krawędziach. Na przykład próba odczytania pikseli 3 jednostek poza krawędzią odczytuje zamiast tego jedną 3 jednostki wewnątrz krawędzi.
Przyciąć
Każdy piksel w obrazie wyjściowym, który wymagałby wartości spoza krawędzi, jest pomijany. Ta metoda może spowodować, że obraz wyjściowy będzie nieco mniejszy, a krawędzie zostaną przycięte.
Uprawa jądra
Żaden piksel w jądrze, który wykracza poza obraz wejściowy, nie jest używany, a normalizacja jest dostosowywana w celu kompensacji.

Normalizacja

Normalizacja jest definiowana jako podział każdego elementu jądra przez sumę wszystkich elementów jądra, tak aby suma elementów znormalizowanego jądra była jednością. Dzięki temu średni piksel w zmodyfikowanym obrazie będzie tak jasny, jak przeciętny piksel w oryginalnym obrazie.

Konkretna realizacja

Oto konkretna implementacja konwolucji wykonana za pomocą języka cieniowania GLSL :

// author : csblo
// Work made just by consulting :
// https://en.wikipedia.org/wiki/Kernel_(image_processing)

// Define kernels
#define identity mat3(0, 0, 0, 0, 1, 0, 0, 0, 0)
#define edge0 mat3(1, 0, -1, 0, 0, 0, -1, 0, 1)
#define edge1 mat3(0, 1, 0, 1, -4, 1, 0, 1, 0)
#define edge2 mat3(-1, -1, -1, -1, 8, -1, -1, -1, -1)
#define sharpen mat3(0, -1, 0, -1, 5, -1, 0, -1, 0)
#define box_blur mat3(1, 1, 1, 1, 1, 1, 1, 1, 1) * 0.1111
#define gaussian_blur mat3(1, 2, 1, 2, 4, 2, 1, 2, 1) * 0.0625
#define emboss mat3(-2, -1, 0, -1, 1, 1, 0, 1, 2)

// Find coordinate of matrix element from index
vec2 kpos(int index)
{
    return vec2[9] (
        vec2(-1, -1), vec2(0, -1), vec2(1, -1),
        vec2(-1, 0), vec2(0, 0), vec2(1, 0), 
        vec2(-1, 1), vec2(0, 1), vec2(1, 1)
    )[index] / iResolution.xy;
}


// Extract region of dimension 3x3 from sampler centered in uv
// sampler : texture sampler
// uv : current coordinates on sampler
// return : an array of mat3, each index corresponding with a color channel
mat3[3] region3x3(sampler2D sampler, vec2 uv)
{
    // Create each pixels for region
    vec4[9] region;
    
    for (int i = 0; i < 9; i++)
        region[i] = texture(sampler, uv + kpos(i));

    // Create 3x3 region with 3 color channels (red, green, blue)
    mat3[3] mRegion;
    
    for (int i = 0; i < 3; i++)
        mRegion[i] = mat3(
        	region[0][i], region[1][i], region[2][i],
        	region[3][i], region[4][i], region[5][i],
        	region[6][i], region[7][i], region[8][i]
    	);
    
    return mRegion;
}

// Convolve a texture with kernel
// kernel : kernel used for convolution
// sampler : texture sampler
// uv : current coordinates on sampler
vec3 convolution(mat3 kernel, sampler2D sampler, vec2 uv)
{
    vec3 fragment;
    
    // Extract a 3x3 region centered in uv
    mat3[3] region = region3x3(sampler, uv);
    
    // for each color channel of region
    for (int i = 0; i < 3; i++)
    {
        // get region channel
        mat3 rc = region[i];
        // component wise multiplication of kernel by region channel
        mat3 c = matrixCompMult(kernel, rc);
        // add each component of matrix
        float r = c[0][0] + c[1][0] + c[2][0]
                + c[0][1] + c[1][1] + c[2][1]
                + c[0][2] + c[1][2] + c[2][2];
        
        // for fragment at channel i, set result
        fragment[i] = r;
    }
    
    return fragment;    
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    // Normalized pixel coordinates (from 0 to 1)
    vec2 uv = fragCoord/iResolution.xy;
    // Convolve kernel with texture
    vec3 col = convolution(emboss, iChannel0, uv);
    
    // Output to screen
    fragColor = vec4(col, 1.0);
}

Bibliografia

  • Ludwig, Jamie (nd). Konwolucja obrazu (PDF) . Uniwersytet Stanowy w Portland .
  • Lecarme, Olivier; Delvare, Karine (styczeń 2013). Księga GIMP: kompletny przewodnik po prawie wszystkim . Bez skrobi Prasa . P. 429. ISBN 978-1593273835.
  • Gumster, Jason van; Szymoński, Robert (marzec 2012). Biblia GIMP-a . Wiley . s. 438–442. Numer ISBN 978-0470523971.
  • Shapiro, Linda G .; Stockman, George C. (luty 2001). Wizja komputerowa . Sala urzędnicza . s. 53–54. Numer ISBN 978-0130307965.

Zobacz też

Zewnętrzne linki