Come faccio a Controllo sfocatura un'immagine senza utilizzare alcuna funzione gaussiana in-built?

StackOverflow https://stackoverflow.com/questions/1696113

Domanda

Voglio sfocatura mia immagine con la formula sfocatura gaussiana nativo. Ho letto l'Wikipedia articolo , ma non sono sicuro come implementare questa.

Come faccio a utilizzare la formula per decidere i pesi?

Non voglio usare qualsiasi costruito nelle funzioni come quello che MATLAB ha

È stato utile?

Soluzione

Scrivi sfocatura gaussiana ingenuo è in realtà piuttosto semplice. E 'fatto esattamente nello stesso modo di qualsiasi altro filtro di convoluzione. L'unica differenza tra una scatola e un filtro gaussiano è la matrice che si usa.

Immaginate di avere un'immagine definita nel seguente modo:

 0  1  2  3  4  5  6  7  8  9
10 11 12 13 14 15 16 17 18 19
20 21 22 23 24 25 26 27 28 29
30 31 32 33 34 35 36 37 38 39
40 41 42 43 44 45 46 47 48 49
50 51 52 53 54 55 56 57 58 59
60 61 62 63 64 65 66 67 68 69
70 71 72 73 74 75 76 77 78 79
80 81 82 83 84 85 86 87 88 89
90 91 92 93 94 95 96 97 98 99

Una matrice del filtro 3x3 è definito come segue:

0.111 0.111 0.111
0.111 0.111 0.111
0.111 0.111 0.111

Per applicare la sfocatura gaussiana si dovrebbe effettuare le seguenti operazioni:

Per pixel 11 sarebbe necessario caricare pixel 0, 1, 2, 10, 11, 12, 20, 21, 22.

si sarebbe quindi moltiplicare pixel 0 dalla parte superiore sinistra del filtro 3x3 sfocatura. Pixel 1 entro la metà superiore, pixel 2, 3 pixel da alto a destra, pixel 10 entro la metà sinistra e così via.

Quindi aggiungere loro del tutto e scrivere il risultato di pixel 11. Come si può vedere Pixel 11 è ora la media di se stesso e dei pixel circostanti.

casi limite fanno ottenere un po 'più complessa. Quali valori si usa per i valori del bordo della trama? Un modo può essere quello di avvolgere intorno verso l'altro lato. Questo sembra buono per un'immagine che viene in seguito piastrellato. Un altro modo è quello di spingere il pixel nei luoghi circostanti.

Quindi, per alto a sinistra è possibile posizionare i campioni come segue:

 0  0  1
 0  0  1
10 10 11

Spero che si può vedere come questo può essere facilmente esteso a grandi kernel di filtro (cioè 5x5 o 9x9, ecc).

La differenza tra un filtro gaussiano e un filtro scatola è i numeri che vanno nella matrice. Un filtro gaussiano utilizza una distribuzione gaussiana in una riga e colonna.

per esempio un filtro definito arbitrariamente come (cioè non è una gaussiana, ma probabilmente non lontano)

0.1 0.8 0.1

prima colonna sarebbe la stessa, ma si applica nel primo elemento della riga sopra.

0.01 0.8 0.1
0.08 
0.01 

La seconda colonna sarebbe lo stesso ma i valori verrebbe moltiplicato per il 0,8 nella riga sopra (e così via).

0.01 0.08 0.01
0.08 0.64 0.08
0.01 0.08 0.01

Il risultato della somma tutto quanto sopra insieme dovrebbe uguale 1. La differenza tra il filtro e il filtro sopra scatola originale sarebbe che il pixel finale scritta avrebbe un peso molto più pesante verso il pixel centrale (cioè quello che è in quella posizione già). La sfocatura si verifica perché i pixel circostanti si confondono in quel pixel, anche se non così tanto. L'utilizzo di questo tipo di filtro si ottiene una sfocatura, ma uno che non distrugge la maggior quantità di alta frequenza (vale a dire un rapido cambiamento del colore da pixel a pixel) informazioni.

Questo genere di filtri in grado di fare un sacco di cose interessanti. Si può fare un bordo rilevare che utilizza questo tipo di filtro sottraendo pixel circostanti dal pixel corrente. Questo lascerà solo i veramente grandi cambiamenti di colore (alte frequenze) dietro.

Modifica:. Un kernel di filtro 5x5 è definire esattamente come sopra

ad esempio, se la riga è di 0,1 0,2 0,4 0,2 0,1 allora se si moltiplica ogni valore nella loro dal primo elemento per formare una colonna e quindi moltiplicare ogni dalla seconda voce per formare la seconda colonna e così via ci si ritroverà con un filtro di

0.01 0.02 0.04 0.02 0.01
0.02 0.04 0.08 0.04 0.02
0.04 0.08 0.16 0.08 0.04
0.02 0.04 0.08 0.04 0.02
0.01 0.02 0.04 0.02 0.01

prendere alcune posizioni arbitrarie si può vedere che la posizione 0, 0 è semplice 0.1 * 0.1. Posizione 0, 2 è 0.1 * 0.4, posizione 2, 2 è 0,4 * 0,4 e posizione 1, 2 è 0,2 * 0,4.

Spero che ti dà una buona spiegazione sufficiente.

Altri suggerimenti

Ecco il pseudo-codice per il codice che ho usato in C # per calcolare il kernel. Non ho il coraggio di dire che io tratto le finali condizioni correttamente, però:

double[] kernel = new double[radius * 2 + 1];
double twoRadiusSquaredRecip = 1.0 / (2.0 * radius * radius);
double sqrtTwoPiTimesRadiusRecip = 1.0 / (sqrt(2.0 * Math.PI) * radius);
double radiusModifier = 1.0;

int r = -radius;
for (int i = 0; i < kernel.Length; i++)
{
    double x = r * radiusModifier;
    x *= x;
    kernel[i] =
    sqrtTwoPiTimesRadiusRecip * Exp(-x * sqrtTwoPiTimesRadiusRecip);
    r++;
}

double div = Sum(kernel);
for (int i = 0; i < kernel.Length; i++)
{
    kernel[i] /= div;
}

Spero che questo può aiutare.

Per usare il kernel di filtro discusso in questo articolo Wikipedia è necessario implementare (discreto) convoluzione . L'idea è che si ha una piccola matrice di valori (kernel), si sposta questa kernel da pixel a pixel nell'immagine (cioè in modo che il centro della matrice è sul pixel), moltiplicare gli elementi di matrice con l'immagine sovrapposta elementi, sommare tutti i valori nel risultato e sostituire il valore del pixel vecchia con questa somma.

sfocatura gaussiana può essere separato in due spire 1D (uno verticale e uno orizzontale) invece di una convoluzione 2D, che accelera anche cose un po '.

Non mi è chiaro se si desidera limitare questa a certe tecnologie, ma se non SVG (ScalableVectorGraphics) ha un'implementazione di Controllo sfocatura. Credo che si applica a tutte le primitive tra pixel. SVG ha il vantaggio di essere uno standard aperto e ampiamente implementato.

Bene, gaussiano kernel è un kernel separabili.
Quindi tutto ciò che serve è una funzione che supporta separabile 2D Convolution come - ImageConvolutionSeparableKernel() .

Una volta che lo avete, tutti bisogno è un wrapper per generare 1D gaussiana Kernel e inviarlo alla funzione, come fatto in ImageConvolutionGaussianKernel() .

Il codice è un'implementazione C dritto in avanti di 2D Immagine convoluzione accelerata da SIMD (SSE) e Multi Threading (OpenMP).

L'intero progetto è dato da - Immagine Convolution - GitHub <. / p>

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top